/**
 * JH 数据可视化仪表板 JavaScript - 个性化增强版
 * 处理数据可视化、用户交互、个性化配置和API调用
 */

class JHDashboard {
    constructor() {
        this.apiBaseUrl = 'http://localhost:8000/api/jh';
        this.charts = {};
        this.currentFilters = {};
        this.currentPage = 1;
        this.pageSize = 33; // 默认33条数据
        this.totalPages = 1;
        this.totalJobs = 0;
        this.isLoading = false;
        this.sortable = null;
        
        // 图表模态框管理
        this.modalChart = null; // 模态框中的图表实例
        this.currentModalChartId = null; // 当前模态框显示的图表ID
        
        // 图表展开状态管理
        this.expandedCharts = new Set(); // 存储展开的图表ID
        
        // 新增：当前页职位与当前查看职位索引/详情
        this.currentJobs = [];
        this.currentJobIndex = -1;
        this.currentJobDetail = null;
        
        // 注册Chart.js插件
        this.registerChartPlugins();
        
        // 个性化配置
        this.userPreferences = {
            theme: 'light',
            chartConfigs: {
                jobTypeChart: { type: 'doughnut', dimension: 'job_type' },
                locationChart: { type: 'bar', dimension: 'location' },
                salaryChart: { type: 'bar', dimension: 'salary_range' },
                timeChart: { type: 'line', dimension: 'daily' },
                skillsChart: { type: 'horizontalBar', dimension: 'top_skills' },
                companyChart: { type: 'bar', dimension: 'job_count' }
            },
            layout: []
        };
        
        this.init();
    }
    
    // 注册Chart.js插件
    registerChartPlugins() {
        try {
            // 注册缩放插件
            if (typeof window.zoomPlugin !== 'undefined') {
                Chart.register(window.zoomPlugin);
            } else if (typeof window.ChartZoom !== 'undefined') {
                Chart.register(window.ChartZoom);
            } else {
                console.warn('Chart.js zoom plugin not found, zoom functionality will be disabled');
            }
        } catch (error) {
            console.warn('Failed to register Chart.js plugins:', error);
        }
    }
    
    async init() {
        console.log('初始化JH个性化数据仪表板...');
        
        // 首先尝试API调用获取真实数据
        try {
            await this.loadOverviewData();
            await this.loadJobsData();
            await this.loadChartsData();
        } catch (error) {
            console.warn('API调用失败，使用Mock数据:', error);
            this.displayMockJobsTable();
            this.loadMockChartsData();
        }
        
        // 初始化其他组件
        this.initializeFilters();
        this.initializeCharts();
        this.initializePersonalization();
        this.initializeDragAndDrop();
        this.loadUserPreferences();
        this.initializeModal();
        this.initializeResizeHandler();
        this.initJobDetailModal();
        
        console.log('✅ JH数据仪表板初始化完成');
    }
    
    // 修改：加载概览数据
    async loadOverviewData() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/overview`);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            this.displayOverviewStats(data);
            console.log('✅ 概览数据加载成功');
        } catch (error) {
            console.error('概览数据加载失败:', error);
            throw error;
        }
    }
    
    // 修改：加载职位数据
    async loadJobsData() {
        try {
            // 获取第一页数据来测试API
            const params = new URLSearchParams({
                page: this.currentPage,
                page_size: this.pageSize,
                ...this.buildQueryParams()
            });
            
            const response = await fetch(`${this.apiBaseUrl}/jobs?${params}`);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            this.displayJobsTable(data.items || []);
            this.updatePagination(data);
            this.totalJobs = data.total_items || 0;
            console.log(`✅ 职位数据加载成功: ${this.totalJobs} 条数据`);
        } catch (error) {
            console.error('职位数据加载失败:', error);
            throw error;
        }
    }
    
    // 修改：加载图表数据
    async loadChartsData() {
        const chartIds = ['jobTypeChart', 'locationChart', 'salaryChart', 'timeChart', 'skillsChart', 'companyChart'];
        const promises = chartIds.map(chartId => this.createChart(chartId));
        
        try {
            await Promise.all(promises);
            console.log('✅ 所有图表数据加载成功');
        } catch (error) {
            console.error('图表数据加载失败:', error);
            throw error;
        }
    }
    
    // 新增：初始化筛选器
    initializeFilters() {
        // 筛选器初始化逻辑
        console.log('初始化筛选器');
    }
    
    // 新增：初始化图表
    initializeCharts() {
        // 图表初始化逻辑
        console.log('初始化图表');
    }
    
    // 新增：初始化个性化设置
    initializePersonalization() {
        // 个性化设置初始化逻辑
        console.log('初始化个性化设置');
    }
    
    // 新增：加载Mock图表数据
    loadMockChartsData() {
        const chartIds = ['jobTypeChart', 'locationChart', 'salaryChart', 'timeChart', 'skillsChart', 'companyChart'];
        chartIds.forEach(chartId => {
            const config = this.userPreferences.chartConfigs[chartId];
            const mockData = this.getMockChartData(chartId, config.dimension, false);
            this.updateChart(chartId, mockData, config.type, config.dimension);
        });
    }
    
    // 新增：构建查询参数
    buildQueryParams() {
        const params = {};
            
        // 添加筛选条件
        if (this.currentFilters.search) {
            params.search = this.currentFilters.search;
        }
        if (this.currentFilters.job_title) {
            params.job_title = this.currentFilters.job_title;
        }
        if (this.currentFilters.company_name) {
            params.company_name = this.currentFilters.company_name;
        }
        if (this.currentFilters.job_location) {
            params.job_location = this.currentFilters.job_location;
        }
        if (this.currentFilters.job_country) {
            params.job_country = this.currentFilters.job_country;
        }
        if (this.currentFilters.job_schedule_type) {
            params.job_schedule_type = this.currentFilters.job_schedule_type;
        }
        if (this.currentFilters.salary_min) {
            params.salary_min = this.currentFilters.salary_min;
        }
        if (this.currentFilters.salary_max) {
            params.salary_max = this.currentFilters.salary_max;
        }
        if (this.currentFilters.work_from_home !== undefined) {
            params.work_from_home = this.currentFilters.work_from_home;
        }
        if (this.currentFilters.skills && this.currentFilters.skills.length > 0) {
            params.skills = this.currentFilters.skills.join(',');
        }
        
        return params;
    }
    
    // 新增：显示概览统计
    displayOverviewStats(stats) {
        // 更新概览卡片
        const updateStat = (id, value, formatter = null) => {
            const element = document.getElementById(id);
            if (element) {
                element.textContent = formatter ? formatter(value) : value;
            }
        };
        
        updateStat('totalJobs', stats.total_jobs || 0, val => val.toLocaleString());
        updateStat('avgSalary', stats.avg_salary || 0, val => `¥${Math.round(val).toLocaleString()}`);
        updateStat('remoteJobs', stats.remote_jobs || 0, val => val.toLocaleString());
        updateStat('totalCompanies', stats.total_companies || 0, val => val.toLocaleString());
        
        // 更新百分比显示
        const remotePercentage = stats.remote_percentage || 0;
        updateStat('remotePercentage', remotePercentage, val => `${val.toFixed(1)}%`);
    }
    
    // 修改：更新职位表格函数
    async updateJobsTable() {
        try {
            // 使用真实API
            const params = new URLSearchParams({
                page: this.currentPage,
                page_size: this.pageSize,
                ...this.buildQueryParams()
            });
            
            const response = await fetch(`${this.apiBaseUrl}/jobs?${params}`);
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            this.displayJobsTable(data.items || []);
            this.updatePagination(data);
            this.totalJobs = data.total_items || 0;
            
        } catch (error) {
            console.error('更新职位表格失败:', error);
            // 回退到Mock数据
            this.displayMockJobsTable();
        }
    }
    
    // 修改：创建图表函数 - 删除重复函数，使用后面的版本
    
    // 加载用户偏好设置
    loadUserPreferences() {
        const saved = localStorage.getItem('jh_dashboard_preferences');
        if (saved) {
            try {
                const preferences = JSON.parse(saved);
                this.userPreferences = { ...this.userPreferences, ...preferences };
            } catch (error) {
                console.warn('加载用户偏好设置失败:', error);
            }
        }
    }
    
    // 保存用户偏好设置
    saveUserPreferences() {
        try {
            localStorage.setItem('jh_dashboard_preferences', JSON.stringify(this.userPreferences));
        } catch (error) {
            console.warn('保存用户偏好设置失败:', error);
        }
    }
    
    // 主题切换功能
    applyTheme(theme) {
        const body = document.body;
        const themeToggle = document.getElementById('themeToggle');
        
        // 移除所有主题类
        body.classList.remove('light-theme', 'dark-theme');
        
        if (theme === 'auto') {
            // 自动检测系统主题
            const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
            theme = prefersDark ? 'dark' : 'light';
        }
        
        body.classList.add(`${theme}-theme`);
        this.userPreferences.theme = theme;
        
        // 更新主题切换按钮图标
        if (themeToggle) {
            const icon = themeToggle.querySelector('i');
            icon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
        }
        
        // 更新配置面板中的主题按钮状态
        this.updateThemeButtons();
        
        this.saveUserPreferences();
    }
    
    // 更新主题按钮状态
    updateThemeButtons() {
        const themeButtons = document.querySelectorAll('.theme-btn');
        themeButtons.forEach(btn => {
            btn.classList.remove('active');
            if (btn.dataset.theme === this.userPreferences.theme) {
                btn.classList.add('active');
            }
        });
    }
    
    // 初始化拖拽功能
    initializeDragAndDrop() {
        const chartsGrid = document.getElementById('chartsGrid');
        if (chartsGrid && typeof Sortable !== 'undefined') {
            this.sortable = Sortable.create(chartsGrid, {
                handle: '.drag-handle',
                animation: 150,
                ghostClass: 'sortable-ghost',
                chosenClass: 'sortable-chosen',
                onEnd: (evt) => {
                    this.saveLayout();
                }
            });
        }
    }
    
    // 保存布局
    saveLayout() {
        const chartsGrid = document.getElementById('chartsGrid');
        if (chartsGrid) {
            const layout = Array.from(chartsGrid.children).map(card => {
                return card.dataset.chartId;
            });
            this.userPreferences.layout = layout;
            this.saveUserPreferences();
        }
    }
    
    // 重置布局
    resetLayout() {
        this.userPreferences.layout = [];
        this.saveUserPreferences();
        
        // 重新排列图表顺序
        const chartsGrid = document.getElementById('chartsGrid');
        const defaultOrder = ['jobTypeChart', 'locationChart', 'salaryChart', 'timeChart', 'skillsChart', 'companyChart'];
        
        defaultOrder.forEach(chartId => {
            const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
            if (chartCard) {
                chartsGrid.appendChild(chartCard);
            }
        });
        
        this.showNotification('布局已重置为默认设置');
    }
    
    // 初始化配置面板
    initializeConfigPanel() {
        this.generateChartConfigList();
        this.updateThemeButtons();
        
        // 绑定主题按钮事件
        const themeButtons = document.querySelectorAll('.theme-btn');
        themeButtons.forEach(btn => {
            btn.addEventListener('click', () => {
                this.applyTheme(btn.dataset.theme);
            });
        });
    }
    
    // 生成图表配置列表
    generateChartConfigList() {
        const configList = document.getElementById('chartConfigList');
        if (!configList) return;
        
        const chartConfigs = [
            { id: 'jobTypeChart', name: '职位类型分布', icon: 'fa-chart-pie' },
            { id: 'locationChart', name: '地区职位分布', icon: 'fa-chart-bar' },
            { id: 'salaryChart', name: '薪资分布', icon: 'fa-chart-area' },
            { id: 'timeChart', name: '时间趋势', icon: 'fa-chart-line' },
            { id: 'skillsChart', name: '技能需求', icon: 'fa-fire' },
            { id: 'companyChart', name: '公司排行', icon: 'fa-trophy' }
        ];
        
        configList.innerHTML = chartConfigs.map(config => `
            <div class="chart-config-item">
                <h5><i class="fas ${config.icon}"></i> ${config.name}</h5>
                <div style="display: flex; gap: 0.5rem; margin-top: 0.5rem;">
                    <button class="btn btn-sm" onclick="dashboard.hideChart('${config.id}')">
                        <i class="fas fa-eye-slash"></i> 隐藏
                    </button>
                    <button class="btn btn-sm" onclick="dashboard.showChart('${config.id}')">
                        <i class="fas fa-eye"></i> 显示
                    </button>
                </div>
            </div>
        `).join('');
    }
    
    // 显示/隐藏图表
    hideChart(chartId) {
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        if (chartCard) {
            chartCard.style.display = 'none';
        }
    }
    
    showChart(chartId) {
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        if (chartCard) {
            chartCard.style.display = 'block';
        }
    }
    
    // 切换图表类型
    changeChartType(chartId, newType) {
        this.userPreferences.chartConfigs[chartId].type = newType;
        this.saveUserPreferences();
        this.refreshChart(chartId);
        this.showNotification('图表类型已更新');
    }
    
    // 切换图表维度
    changeDimension(chartId, newDimension) {
        this.userPreferences.chartConfigs[chartId].dimension = newDimension;
        this.saveUserPreferences();
        this.refreshChart(chartId);
        this.showNotification('图表维度已更新');
    }
    
    showLoading() {
        const overlay = document.getElementById('loadingOverlay');
        if (overlay) {
            overlay.classList.add('active');
        }
    }
    
    hideLoading() {
        const overlay = document.getElementById('loadingOverlay');
        if (overlay) {
            overlay.classList.remove('active');
        }
    }
    
    showError(message) {
        this.showNotification(message, 'error');
    }
    
    showNotification(message, type = 'success') {
        // 创建通知元素
        const notification = document.createElement('div');
        notification.className = `notification notification-${type}`;
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: ${type === 'error' ? '#ef4444' : '#10b981'};
            color: white;
            padding: 1rem 1.5rem;
            border-radius: 8px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
            z-index: 10000;
            animation: slideIn 0.3s ease;
        `;
        notification.textContent = message;
        
        document.body.appendChild(notification);
        
        // 3秒后自动移除
            setTimeout(() => {
            notification.style.animation = 'slideOut 0.3s ease';
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.parentNode.removeChild(notification);
                }
            }, 300);
            }, 3000);
    }
    
    async loadOverviewStats() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/overview`);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const stats = await response.json();
            this.displayOverviewStats(stats);
            
        } catch (error) {
            console.error('加载概览统计失败:', error);
            this.displayMockOverviewStats();
        }
    }
    
    displayOverviewStats(stats) {
        const elements = {
            totalJobs: document.getElementById('totalJobs'),
            totalCompanies: document.getElementById('totalCompanies'),
            topLocation: document.getElementById('topLocation'),
            avgSalary: document.getElementById('avgSalary')
        };
        
        if (elements.totalJobs) elements.totalJobs.textContent = this.formatNumber(stats.total_jobs || 0);
        if (elements.totalCompanies) elements.totalCompanies.textContent = this.formatNumber(stats.total_companies || 0);
        if (elements.topLocation) elements.topLocation.textContent = stats.top_location || 'N/A';
        if (elements.avgSalary) elements.avgSalary.textContent = stats.avg_salary ? '$' + this.formatNumber(Math.round(stats.avg_salary)) : 'N/A';
    }
    
    displayMockOverviewStats() {
        const mockStats = {
            total_jobs: 22003,
            total_companies: 3247,
            top_location: '美国',
            avg_salary: 123286
        };
        this.displayOverviewStats(mockStats);
    }
    
    formatNumber(num) {
        return num.toLocaleString();
    }
    
    async initializeCharts() {
        const chartIds = ['jobTypeChart', 'locationChart', 'salaryChart', 'timeChart', 'skillsChart', 'companyChart'];
        
        for (const chartId of chartIds) {
            await this.createChart(chartId);
        }
        
        // 应用保存的布局
        this.applyLayout();
        
        // 同步所有图表控件状态
        this.syncAllChartControls();
    }
    
    // 应用保存的布局
    applyLayout() {
        if (this.userPreferences.layout && this.userPreferences.layout.length > 0) {
            const chartsGrid = document.getElementById('chartsGrid');
            this.userPreferences.layout.forEach(chartId => {
                const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
                if (chartCard) {
                    chartsGrid.appendChild(chartCard);
                }
            });
        }
    }
    
    // 初始化标签筛选器
    async initializeTagFilters() {
        try {
            // 获取筛选选项数据
            const filterData = await this.getFilterOptions();
            
            // 生成工作类型标签
            this.generateScheduleTags(filterData.scheduleTypes);
            
            // 生成国家标签
            this.generateCountryTags(filterData.countries);
            
            // 绑定标签点击事件
            this.bindTagEvents();
            
        } catch (error) {
            console.error('初始化标签筛选器失败:', error);
        }
    }
    
    // 获取筛选选项数据
    async getFilterOptions() {
        try {
            const response = await fetch(`${this.apiBaseUrl}/filter-options`);
            if (!response.ok) {
                throw new Error('Failed to fetch filter options');
            }
            return await response.json();
        } catch (error) {
            console.error('获取筛选选项失败:', error);
            // 返回模拟数据
            return {
                scheduleTypes: ['Full-time', 'Part-time', 'Contractor', 'Temp work', 'Internship'],
                countries: ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia', 'Mexico', 'France', 'Brazil', 'Netherlands', 'Denmark']
            };
        }
    }
    
    // 生成工作类型标签
    generateScheduleTags(scheduleTypes) {
        const container = document.getElementById('scheduleTagGroup');
        if (!container) return;
        
        container.innerHTML = '';
        
        scheduleTypes.forEach(type => {
            const tag = document.createElement('div');
            tag.className = 'filter-tag';
            tag.dataset.filter = 'job_schedule_type';
            tag.dataset.value = type;
            
            const icon = this.getScheduleIcon(type);
            tag.innerHTML = `
                <span>${type}</span>
                <i class="fas ${icon}"></i>
            `;
            
            container.appendChild(tag);
        });
    }
    
    // 生成国家标签
    generateCountryTags(countries) {
        const container = document.getElementById('countryTagGroup');
        if (!container) return;
        
        container.innerHTML = '';
        
        countries.forEach(country => {
            const tag = document.createElement('div');
            tag.className = 'filter-tag';
            tag.dataset.filter = 'job_country';
            tag.dataset.value = country;
            
            const flag = this.getCountryFlag(country);
            tag.innerHTML = `
                <span>${country}</span>
                ${flag}
            `;
            
            container.appendChild(tag);
        });
    }
    
    // 获取工作类型图标
    getScheduleIcon(type) {
        const icons = {
            'Full-time': 'fa-clock',
            'Part-time': 'fa-clock-o',
            'Contractor': 'fa-handshake',
            'Temp work': 'fa-calendar-alt',
            'Internship': 'fa-graduation-cap',
            'Contract': 'fa-handshake'
        };
        return icons[type] || 'fa-briefcase';
    }
    
    // 获取国家旗帜或图标
    getCountryFlag(country) {
        const flags = {
            'United States': '🇺🇸',
            'Germany': '🇩🇪',
            'Canada': '🇨🇦',
            'United Kingdom': '🇬🇧',
            'Australia': '🇦🇺',
            'Mexico': '🇲🇽',
            'France': '🇫🇷',
            'Brazil': '🇧🇷',
            'Netherlands': '🇳🇱',
            'Denmark': '🇩🇰'
        };
        return flags[country] || '<i class="fas fa-globe"></i>';
    }
    
    // 绑定标签事件
    bindTagEvents() {
        const filterTags = document.querySelectorAll('.filter-tag');
        filterTags.forEach(tag => {
            tag.addEventListener('click', () => {
                this.toggleFilterTag(tag);
            });
        });
    }
    
    // 重新绑定所有筛选事件（包括静态的远程工作标签）
    rebindFilterEvents() {
        // 重新绑定所有筛选标签事件
        this.bindTagEvents();
    }
    
    // 切换筛选标签状态
    toggleFilterTag(tag) {
        const isActive = tag.classList.contains('active');
        const filterField = tag.dataset.filter;
        const filterValue = tag.dataset.value;
        
        if (isActive) {
            // 移除筛选
            tag.classList.remove('active');
            delete this.currentFilters[filterField];
        } else {
            // 添加筛选（先清除同类型的其他筛选）
            const sameTypeActiveTags = document.querySelectorAll(`.filter-tag[data-filter="${filterField}"].active`);
            sameTypeActiveTags.forEach(activeTag => {
                activeTag.classList.remove('active');
            });
            
            tag.classList.add('active');
            this.currentFilters[filterField] = filterValue;
        }
        
        // 更新活跃筛选显示
        this.updateActiveFilters();
        
        // 重新加载数据
        this.currentPage = 1;
        this.loadJobsTable();
    }
    
    async createChart(chartId) {
        try {
            const config = this.userPreferences.chartConfigs[chartId];
            const data = await this.getChartData(chartId, config.dimension);
            const chartConfig = this.getChartConfig(config.type, data, chartId);
            
            const canvas = document.getElementById(chartId);
            if (!canvas) return;
            
            // 销毁现有图表
            if (this.charts[chartId]) {
                this.charts[chartId].destroy();
            }
            
            // 创建新图表
            const ctx = canvas.getContext('2d');
            this.charts[chartId] = new Chart(ctx, chartConfig);
            
            // 更新图表标题
            this.updateChartTitle(chartId, config.dimension);
            
            // 同步表头控件状态
            this.syncChartControls(chartId, config.type, config.dimension);
            
        } catch (error) {
            console.error(`创建图表 ${chartId} 失败:`, error);
        }
    }
    
    // 更新图表标题
    updateChartTitle(chartId, dimension) {
        const titleElement = document.querySelector(`[data-chart-id="${chartId}"] .chart-title`);
        if (!titleElement) return;
        
        const dimensionNames = {
            // 职位类型图
            job_type: '职位类型分布',
            schedule_type: '工作类型分布',
            remote_type: '远程类型分布',
            
            // 地区图
            location: '地区职位分布',
            country: '国家职位分布',
            city: '城市职位分布',
            
            // 薪资图
            salary_range: '薪资范围分布',
            avg_by_type: '各职位类型平均薪资',
            avg_by_location: '各地区平均薪资',
            
            // 时间图
            daily: '每日发布趋势',
            weekly: '每周发布趋势',
            monthly: '每月发布趋势',
            
            // 技能图
            top_skills: '热门技能需求',
            skills_by_type: '各职位类型技能需求',
            emerging_skills: '新兴技能趋势',
            
            // 公司图
            job_count: '招聘职位数量排行',
            avg_salary: '平均薪资排行',
            growth_rate: '增长率排行'
        };
        
        titleElement.textContent = dimensionNames[dimension] || titleElement.textContent;
    }
    
    async refreshChart(chartId, expanded = null) {
        console.log(`刷新图表: ${chartId}`);
        
        // 如果没有明确指定展开状态，使用当前状态
        if (expanded === null) {
            expanded = this.expandedCharts.has(chartId);
        }
        
        try {
            const config = this.userPreferences.chartConfigs[chartId];
            if (!config) {
                console.warn(`图表配置不存在: ${chartId}`);
                return;
            }
            
            const data = await this.getChartData(chartId, config.dimension, expanded);
            this.updateChart(chartId, data, config.type, config.dimension);
            
        } catch (error) {
            console.error(`刷新图表失败 (${chartId}):`, error);
            this.showNotification(`刷新图表失败: ${chartId}`, 'error');
        }
    }
    
    async getChartData(chartId, dimension, expanded = false) {
        try {
            // 添加expanded参数到API调用
            const url = `${this.apiBaseUrl}/chart-data/${chartId}?dimension=${dimension}&expanded=${expanded}`;
            const response = await fetch(url);
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            return data;
            
        } catch (error) {
            console.error(`获取图表数据失败 (${chartId}):`, error);
            return this.getMockChartData(chartId, dimension, expanded);
        }
    }
    
    getMockChartData(chartId, dimension, expanded = false) {
        const mockData = {
            jobTypeChart: {
                job_type: { 
                    labels: expanded ? 
                        ['Data Scientist', 'Data Engineer', 'Data Analyst', 'Software Engineer', 'Machine Learning Engineer', 'Business Analyst', 'Product Manager', 'DevOps Engineer', 'Full Stack Developer', 'Backend Developer', 'Frontend Developer', 'Mobile Developer'] : 
                        ['Data Scientist', 'Data Engineer', 'Data Analyst', 'Software Engineer', 'Machine Learning Engineer'], 
                    values: expanded ? 
                        [3245, 2891, 4123, 3567, 1821, 1456, 1234, 1123, 987, 876, 765, 654] : 
                        [3245, 2891, 4123, 3567, 1821] 
                },
                schedule_type: { 
                    labels: expanded ? 
                        ['Full-time', 'Part-time', 'Contractor', 'Internship', 'Freelance', 'Temporary'] : 
                        ['Full-time', 'Part-time', 'Contractor', 'Internship'], 
                    values: expanded ? 
                        [12847, 1234, 987, 779, 567, 345] : 
                        [12847, 1234, 987, 779] 
                },
                remote_type: { 
                    labels: expanded ? 
                        ['Fully Remote', 'Hybrid', 'On-site', 'Remote-friendly', 'Flexible'] : 
                        ['Fully Remote', 'Hybrid', 'On-site'], 
                    values: expanded ? 
                        [5847, 6234, 3766, 2345, 1567] : 
                        [5847, 6234, 3766] 
                }
            },
            locationChart: {
                location: { 
                    labels: expanded ? 
                        ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia', 'Netherlands', 'France', 'Brazil', 'India', 'Japan', 'Singapore', 'Sweden', 'Switzerland', 'Norway', 'Denmark'] : 
                        ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia'], 
                    values: expanded ? 
                        [8945, 2341, 1876, 1654, 1031, 876, 734, 656, 578, 456, 345, 234, 198, 167, 145] : 
                        [8945, 2341, 1876, 1654, 1031] 
                },
                country: { 
                    labels: expanded ? 
                        ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia', 'Netherlands', 'France', 'Brazil', 'India', 'Japan'] : 
                        ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia', 'Netherlands'], 
                    values: expanded ? 
                        [8945, 2341, 1876, 1654, 1031, 876, 734, 656, 578, 456] : 
                        [8945, 2341, 1876, 1654, 1031, 876] 
                },
                city: { 
                    labels: expanded ? 
                        ['New York', 'San Francisco', 'Los Angeles', 'Seattle', 'Chicago', 'Boston', 'Austin', 'Denver', 'Toronto', 'London', 'Berlin', 'Amsterdam'] : 
                        ['New York', 'San Francisco', 'Los Angeles', 'Seattle', 'Chicago'], 
                    values: expanded ? 
                        [2341, 2156, 1987, 1654, 1432, 1234, 1098, 987, 876, 765, 654, 543] : 
                        [2341, 2156, 1987, 1654, 1432] 
                }
            },
            salaryChart: {
                salary_range: { 
                    labels: expanded ? 
                        ['40K-60K', '60K-80K', '80K-100K', '100K-120K', '120K-140K', '140K-160K', '160K-180K', '180K-200K', '200K+'] : 
                        ['40K-60K', '60K-80K', '80K-100K', '100K-120K', '120K+'], 
                    values: expanded ? 
                        [1234, 3456, 4567, 3890, 2700, 2345, 1890, 1456, 1234] : 
                        [1234, 3456, 4567, 3890, 2700] 
                },
                avg_by_type: { 
                    labels: expanded ? 
                        ['Data Scientist', 'Data Engineer', 'Software Engineer', 'Data Analyst', 'ML Engineer', 'DevOps Engineer', 'Product Manager', 'Business Analyst'] : 
                        ['Data Scientist', 'Data Engineer', 'Software Engineer', 'Data Analyst'], 
                    values: expanded ? 
                        [115000, 108000, 102000, 78000, 112000, 105000, 125000, 85000] : 
                        [115000, 108000, 102000, 78000] 
                },
                avg_by_location: { 
                    labels: expanded ? 
                        ['San Francisco', 'New York', 'Seattle', 'Los Angeles', 'Chicago', 'Boston', 'Austin', 'Denver', 'Toronto', 'London'] : 
                        ['San Francisco', 'New York', 'Seattle', 'Los Angeles', 'Chicago'], 
                    values: expanded ? 
                        [145000, 125000, 115000, 108000, 95000, 118000, 102000, 98000, 85000, 78000] : 
                        [145000, 125000, 115000, 108000, 95000] 
                }
            },
            timeChart: {
                daily: { 
                    labels: expanded ? 
                        ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7', 'Day 8', 'Day 9', 'Day 10', 'Day 11', 'Day 12', 'Day 13', 'Day 14'] : 
                        ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7'], 
                    values: expanded ? 
                        [156, 189, 178, 203, 245, 167, 134, 198, 176, 221, 189, 203, 234, 187] : 
                        [156, 189, 178, 203, 245, 167, 134] 
                },
                weekly: { 
                    labels: expanded ? 
                        ['Week 1', 'Week 2', 'Week 3', 'Week 4', 'Week 5', 'Week 6', 'Week 7', 'Week 8'] : 
                        ['Week 1', 'Week 2', 'Week 3', 'Week 4'], 
                    values: expanded ? 
                        [1234, 1456, 1567, 1389, 1478, 1523, 1345, 1287] : 
                        [1234, 1456, 1567, 1389] 
                },
                monthly: { 
                    labels: expanded ? 
                        ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] : 
                        ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'], 
                    values: expanded ? 
                        [4567, 4890, 5234, 5678, 5432, 5789, 5234, 5456, 5123, 5345, 5567, 5789] : 
                        [4567, 4890, 5234, 5678, 5432, 5789] 
                }
            },
            skillsChart: {
                top_skills: { 
                    labels: expanded ? 
                        ['Python', 'SQL', 'R', 'Java', 'JavaScript', 'Tableau', 'Spark', 'AWS', 'Docker', 'Kubernetes', 'TensorFlow', 'PyTorch', 'React', 'Node.js', 'MongoDB', 'PostgreSQL', 'Git', 'Linux', 'Pandas', 'NumPy'] : 
                        ['Python', 'SQL', 'R', 'Java', 'JavaScript', 'Tableau', 'Spark', 'AWS'], 
                    values: expanded ? 
                        [8945, 7234, 5678, 4567, 4321, 3456, 2890, 2567, 2345, 2123, 1987, 1876, 1654, 1543, 1432, 1321, 1234, 1123, 1012, 987] : 
                        [8945, 7234, 5678, 4567, 4321, 3456, 2890, 2567] 
                },
                skills_by_type: { 
                    labels: expanded ? 
                        ['Python', 'SQL', 'Machine Learning', 'Statistics', 'Data Visualization', 'Big Data', 'Cloud Computing', 'API Development'] : 
                        ['Python', 'SQL', 'Machine Learning', 'Statistics'], 
                    values: expanded ? 
                        [3456, 2890, 2345, 1987, 1765, 1543, 1432, 1234] : 
                        [3456, 2890, 2345, 1987] 
                },
                emerging_skills: { 
                    labels: expanded ? 
                        ['GPT/LLM', 'Kubernetes', 'MLOps', 'Snowflake', 'DataBricks', 'Streamlit', 'FastAPI', 'GraphQL', 'Kafka', 'Redis'] : 
                        ['GPT/LLM', 'Kubernetes', 'MLOps', 'Snowflake'], 
                    values: expanded ? 
                        [1234, 987, 876, 654, 543, 432, 365, 298, 234, 187] : 
                        [1234, 987, 876, 654] 
                }
            },
            companyChart: {
                job_count: { 
                    labels: expanded ? 
                        ['Google', 'Microsoft', 'Amazon', 'Apple', 'Meta', 'Netflix', 'Tesla', 'Nvidia', 'OpenAI', 'Anthropic', 'Uber', 'Airbnb', 'Spotify', 'Adobe', 'Salesforce'] : 
                        ['Google', 'Microsoft', 'Amazon', 'Apple', 'Meta', 'Netflix'], 
                    values: expanded ? 
                        [456, 389, 367, 298, 245, 189, 167, 145, 134, 123, 112, 98, 87, 76, 65] : 
                        [456, 389, 367, 298, 245, 189] 
                },
                avg_salary: { 
                    labels: expanded ? 
                        ['Netflix', 'Google', 'Meta', 'Apple', 'Microsoft', 'Amazon', 'Tesla', 'Nvidia', 'OpenAI', 'Anthropic'] : 
                        ['Netflix', 'Google', 'Meta', 'Apple', 'Microsoft'], 
                    values: expanded ? 
                        [185000, 165000, 158000, 152000, 148000, 145000, 172000, 178000, 195000, 188000] : 
                        [185000, 165000, 158000, 152000, 148000] 
                },
                growth_rate: { 
                    labels: expanded ? 
                        ['Tesla', 'Nvidia', 'OpenAI', 'Anthropic', 'Uber', 'Airbnb', 'Spotify', 'Adobe'] : 
                        ['Tesla', 'Nvidia', 'OpenAI', 'Anthropic'], 
                    values: expanded ? 
                        [45, 38, 67, 89, 23, 18, 15, 12] : 
                        [45, 38, 67, 89] 
                }
            }
        };
        
        return mockData[chartId]?.[dimension] || { labels: [], values: [] };
    }
    
    getChartConfig(chartType, data, chartId) {
        const colors = [
            '#667eea', '#764ba2', '#f093fb', '#f5576c', '#4facfe', '#00f2fe',
            '#43e97b', '#38f9d7', '#ffecd2', '#fcb69f', '#a8edea', '#fed6e3',
            '#ff9a9e', '#fecfef', '#fecfef', '#a8edea'
        ];
        
        const baseConfig = {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    position: chartType === 'horizontalBar' ? 'top' : 'bottom',
                    labels: {
                        usePointStyle: true,
                        padding: 20
                    }
                },
                tooltip: {
                    backgroundColor: 'rgba(0, 0, 0, 0.8)',
                    titleColor: '#fff',
                    bodyColor: '#fff',
                    borderColor: '#667eea',
                    borderWidth: 1
                }
            },
            scales: {}
        };
        
        switch (chartType) {
            case 'doughnut':
                return {
                    type: 'doughnut',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            data: data.values,
                            backgroundColor: colors,
                            borderWidth: 2,
                            borderColor: '#fff',
                            hoverBorderWidth: 3
                        }]
                    },
                    options: {
                        ...baseConfig,
                        cutout: '60%'
                    }
                };
                
            case 'bar':
                baseConfig.scales = {
                    y: { beginAtZero: true },
                    x: {}
                };
                
                return {
                    type: 'bar',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            data: data.values,
                            backgroundColor: colors[0],
                            borderColor: colors[1],
                            borderWidth: 1,
                            borderRadius: 4
                        }]
                    },
                    options: {
                        ...baseConfig,
                        plugins: {
                            ...baseConfig.plugins,
                            legend: { display: false }
                        }
                    }
                };
                
            case 'horizontalBar':
                baseConfig.scales = {
                    x: { beginAtZero: true },
                    y: {}
                };
                
                return {
                    type: 'bar',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            data: data.values,
                            backgroundColor: colors.slice(0, data.labels.length),
                            borderWidth: 1,
                            borderRadius: 4
                        }]
                    },
                    options: {
                        ...baseConfig,
                        indexAxis: 'y',
                        plugins: {
                            ...baseConfig.plugins,
                            legend: { display: false }
                        }
                    }
                };
                
            case 'line':
                baseConfig.scales = {
                    y: { beginAtZero: true },
                    x: {}
                };
                
                return {
                    type: 'line',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            label: '数量',
                            data: data.values,
                            borderColor: colors[0],
                            backgroundColor: colors[0] + '20',
                            fill: true,
                            tension: 0.4,
                            pointBackgroundColor: colors[0],
                            pointBorderColor: '#fff',
                            pointBorderWidth: 2,
                            pointRadius: 5
                        }]
                    },
                    options: baseConfig
                };
                
            case 'area':
                baseConfig.scales = {
                    y: { beginAtZero: true },
                    x: {}
                };
                
                return {
                    type: 'line',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            label: '数量',
                            data: data.values,
                            borderColor: colors[0],
                            backgroundColor: colors[0] + '40',
                            fill: true,
                            tension: 0.4
                        }]
                    },
                    options: baseConfig
                };
                
            case 'radar':
                return {
                    type: 'radar',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            label: '数量',
                            data: data.values,
                            borderColor: colors[0],
                            backgroundColor: colors[0] + '20',
                            pointBackgroundColor: colors[0],
                            pointBorderColor: '#fff',
                            pointHoverBackgroundColor: '#fff',
                            pointHoverBorderColor: colors[0]
                        }]
                    },
                    options: {
                        ...baseConfig,
                        scales: {
                            r: { beginAtZero: true }
                        }
                    }
                };
                
            default:
                return baseConfig;
        }
    }
    
    async loadJobsTable() {
        try {
            const params = new URLSearchParams({
                page: this.currentPage,
                page_size: this.pageSize,
                ...this.currentFilters
            });
            
            const response = await fetch(`${this.apiBaseUrl}/jobs?${params}`);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const result = await response.json();
            this.displayJobsTable(result.jobs);
            this.updatePagination(result.pagination);
            this.totalJobs = result.pagination.total_items;
            
        } catch (error) {
            console.error('加载职位表格失败:', error);
            this.displayMockJobsTable();
        }
    }
    
    displayJobsTable(jobs) {
        const tbody = document.getElementById('jobsTableBody');
        if (!tbody) return;
        
        // 新增：保存当前页职位数据，便于详情页上下切换
        this.currentJobs = Array.isArray(jobs) ? jobs : [];
        
        tbody.innerHTML = '';
        
        jobs.forEach(job => {
            const row = document.createElement('tr');
            const fullTitle = job.job_title || '';
            const shortTitle = job.job_title_short || fullTitle || 'N/A';
            const isRemote = job.job_work_from_home == 1;
            row.innerHTML = `
                <td>
                    <div title="${this.escapeHtml(fullTitle)}">
                        <strong class="job-title-cell">${this.escapeHtml(shortTitle)}</strong>
                        <div class="job-title-sub" title="${this.escapeHtml(fullTitle)}">
                            ${this.escapeHtml(fullTitle)}
                        </div>
                    </div>
                </td>
                <td>${this.escapeHtml(job.company_name || 'N/A')}</td>
                <td>${this.escapeHtml(job.job_location || 'N/A')}</td>
                <td>${this.escapeHtml(job.job_schedule_type || 'N/A')}</td>
                <td>${job.salary_year_avg ? '$' + job.salary_year_avg.toLocaleString() : 'N/A'}</td>
                <td>${this.formatDate(job.job_posted_date)}</td>
                <td>${this.formatSkills(job.job_skills)}</td>
                <td class="remote-col">
                    <span class="remote-badge compact ${isRemote ? 'remote-yes' : 'remote-no'}" title="${isRemote ? '远程工作' : '现场办公'}">
                        <i class="fas ${isRemote ? 'fa-home' : 'fa-building'}"></i>
                        ${isRemote ? '远程' : '现场'}
                    </span>
                </td>
                <td>
                    <button class="btn btn-sm btn-primary action-btn" onclick="jhDashboard.viewJobDetails('${job.id || ''}')">
                        <i class="fas fa-eye"></i> 查看
                    </button>
                </td>
            `;
            tbody.appendChild(row);
        });
    }
    
    // 更新活跃筛选显示
    updateActiveFilters() {
        const activeFiltersContainer = document.getElementById('activeFilters');
        const filterCount = document.getElementById('filterCount');
        
        // 清空容器
        if (activeFiltersContainer) activeFiltersContainer.innerHTML = '';
        
        const activeFilterEntries = Object.entries(this.currentFilters).filter(([key]) => key !== 'search');
        
        // 更新筛选计数
        if (filterCount) {
            if (activeFilterEntries.length > 0) {
                filterCount.textContent = activeFilterEntries.length;
                filterCount.style.display = 'block';
            } else {
                filterCount.style.display = 'none';
            }
        }
        
        // 显示完整的活跃筛选（如果存在activeFiltersContainer容器）
        activeFilterEntries.forEach(([key, value]) => {
            const displayName = this.getFilterDisplayName(key, value);
            
            // 完整筛选标签
            if (activeFiltersContainer) {
                const chip = document.createElement('div');
                chip.className = 'active-filter-chip';
                chip.innerHTML = `
                    <span>${displayName}</span>
                    <button class="remove-filter" onclick="dashboard.removeFilter('${key}')">
                        <i class="fas fa-times"></i>
                    </button>
                `;
                activeFiltersContainer.appendChild(chip);
            }
        });
    }
    
    // 切换筛选器面板
    toggleFilters() {
        const filtersPanel = document.getElementById('filtersPanel');
        const toggleBtn = document.getElementById('filterToggleBtn');
        
        if (!filtersPanel || !toggleBtn) return;
        
        const isVisible = filtersPanel.style.display !== 'none';
        
        if (isVisible) {
            filtersPanel.style.display = 'none';
            toggleBtn.classList.remove('active');
        } else {
            filtersPanel.style.display = 'block';
            toggleBtn.classList.add('active');
        }
    }
    
    // 更新筛选器计数
    updateFilterCount() {
        const filterCount = document.getElementById('filterCount');
        if (filterCount) {
            // 只计算有效的筛选器（排除空值、空字符串和未定义值）
            const activeFiltersCount = Object.entries(this.currentFilters || {})
                .filter(([key, value]) => value !== '' && value !== null && value !== undefined)
                .length;
            filterCount.textContent = activeFiltersCount;
            filterCount.style.display = activeFiltersCount > 0 ? 'inline-block' : 'none';
        }
    }
    
    // 新增：标签页切换功能
    switchFilterTab(tabName, element) {
        // 移除所有标签页的active类
        document.querySelectorAll('.filter-tab').forEach(tab => {
            tab.classList.remove('active');
        });
        
        // 添加当前标签页的active类
        element.classList.add('active');
        
        // 隐藏所有内容区域
        document.querySelectorAll('.filter-tab-content').forEach(content => {
            content.classList.remove('active');
        });
        
        // 显示对应的内容区域
        const targetContent = document.getElementById(tabName + 'Tab');
        if (targetContent) {
            targetContent.classList.add('active');
        }
    }

    // 移除单个筛选器
    removeSingleFilter(filterKey) {
        if (!this.currentFilters) return;
        
        delete this.currentFilters[filterKey];
        
        // 重置对应的UI元素
        this.resetFilterUI(filterKey);
        
        // 重新加载数据和更新显示
        this.currentPage = 1;
        this.loadJobsTable();
        this.updateActiveFilters();
        this.updateFilterCount();
        
        // 中文通知消息
        const filterKeyLabels = {
            'job_type': '职位类型',
            'job_country': '工作地点',
            'job_schedule_type': '工作类型',
            'job_work_from_home': '远程工作',
            'salary_min': '最低薪资',
            'salary_max': '最高薪资',
            'search': '搜索关键词'
        };
        
        const keyLabel = filterKeyLabels[filterKey] || filterKey.replace('_', ' ');
        this.showNotification(`已移除筛选条件: ${keyLabel}`);
    }
    
    // 重置筛选器UI
    resetFilterUI(filterKey) {
        const filterMappings = {
            'job_type': 'jobType',
            'job_country': 'country', 
            'job_schedule_type': 'schedule',
            'job_work_from_home': 'remote'
        };
        
        // 重置标签式筛选器
        const reverseMapping = Object.entries(filterMappings).find(([key, value]) => key === filterKey);
        if (reverseMapping) {
            const uiKey = reverseMapping[1];
            const group = document.querySelector(`#${uiKey}Filters`);
            if (group) {
                // 移除所有active类
                group.querySelectorAll('.filter-tag').forEach(tag => {
                    tag.classList.remove('active');
                });
                // 激活"All"选项
                const allOption = group.querySelector('.filter-tag[data-value=""]');
                if (allOption) {
                    allOption.classList.add('active');
                }
            }
        }
        
        // 重置薪资输入框
        if (filterKey === 'salary_min') {
            const salaryMin = document.getElementById('salaryMin');
            if (salaryMin) salaryMin.value = '';
        }
        if (filterKey === 'salary_max') {
            const salaryMax = document.getElementById('salaryMax');
            if (salaryMax) salaryMax.value = '';
        }
        
        // 重置搜索框
        if (filterKey === 'search') {
            const searchInput = document.getElementById('searchInput');
            if (searchInput) searchInput.value = '';
        }
    }
    
    // 获取筛选器显示名称
    getFilterDisplayName(key, value) {
        const fieldNames = {
            job_schedule_type: 'Schedule',
            job_work_from_home: 'Remote',
            job_country: 'Country',
            salary_min: 'Min Salary',
            salary_max: 'Max Salary'
        };
        
        const fieldName = fieldNames[key] || key;
        
        if (key === 'job_work_from_home') {
            return `${fieldName}: ${value == 1 ? 'Remote' : 'On-site'}`;
        }
        
        return `${fieldName}: ${value}`;
    }
    
    // 移除单个筛选器
    removeFilter(filterKey) {
        delete this.currentFilters[filterKey];
        
        // 更新对应的标签状态
        const relatedTag = document.querySelector(`.filter-tag[data-filter="${filterKey}"].active`);
        if (relatedTag) {
            relatedTag.classList.remove('active');
        }
        
        // 清除薪资输入框
        if (filterKey === 'salary_min' || filterKey === 'salary_max') {
            const input = document.getElementById(filterKey === 'salary_min' ? 'salaryMin' : 'salaryMax');
            if (input) input.value = '';
        }
        
        // 更新显示和重新加载数据
        this.updateActiveFilters();
        this.currentPage = 1;
        this.loadJobsTable();
    }
    
    // 应用薪资筛选
    applySalaryFilter() {
        const minInput = document.getElementById('salaryMin');
        const maxInput = document.getElementById('salaryMax');
        
        const minValue = minInput?.value ? parseInt(minInput.value) : null;
        const maxValue = maxInput?.value ? parseInt(maxInput.value) : null;
        
        if (minValue !== null && minValue > 0) {
            this.currentFilters.salary_min = minValue;
        } else {
            delete this.currentFilters.salary_min;
        }
        
        if (maxValue !== null && maxValue > 0) {
            this.currentFilters.salary_max = maxValue;
        } else {
            delete this.currentFilters.salary_max;
        }
        
        this.updateActiveFilters();
        this.currentPage = 1;
        this.loadJobsTable();
        
        this.showNotification('Salary filter applied');
    }
    
    // 重置所有筛选器
    resetAllFilters() {
        // 清除所有筛选条件
        this.currentFilters = {};
        
        // 清除活跃标签
        const activeTags = document.querySelectorAll('.filter-tag.active');
        activeTags.forEach(tag => tag.classList.remove('active'));
        
        // 清除输入框
        const inputs = ['salaryMin', 'salaryMax', 'searchInput'];
        inputs.forEach(id => {
            const input = document.getElementById(id);
            if (input) input.value = '';
        });
        
        // 更新显示和重新加载数据
        this.updateActiveFilters();
        this.currentPage = 1;
        this.loadJobsTable();
        
        // 关闭筛选器面板
        const filtersPanel = document.getElementById('filtersPanel');
        const toggleBtn = document.querySelector('.filter-toggle-btn');
        if (filtersPanel) filtersPanel.style.display = 'none';
        if (toggleBtn) toggleBtn.classList.remove('active');
        
        this.showNotification('All filters reset');
    }
    
    displayMockJobsTable() {
        // 生成更大的模拟数据集进行筛选
        const allMockJobs = this.generateLargeMockDataset();
        
        // 应用筛选条件
        const filteredJobs = this.applyFiltersToMockData(allMockJobs);
        
        // 计算分页
        const totalFiltered = filteredJobs.length;
        const startIndex = (this.currentPage - 1) * this.pageSize;
        const endIndex = startIndex + this.pageSize;
        const pageJobs = filteredJobs.slice(startIndex, endIndex);
        
        this.displayJobsTable(pageJobs);
        
        // 更新分页信息
        this.updatePagination({
            page: this.currentPage,
            page_size: this.pageSize,
            total_items: totalFiltered,
            total_pages: Math.ceil(totalFiltered / this.pageSize)
        });
        this.totalJobs = totalFiltered;
    }
    
    generateLargeMockDataset() {
        const jobTitles = ['Senior Data Scientist', 'Data Engineer', 'Software Engineer', 'Data Analyst', 'Machine Learning Engineer'];
        const fullTitles = [
            'Senior Data Scientist - AI/ML Focus',
            'Data Engineer - Cloud Infrastructure',
            'Software Engineer - Full Stack',
            'Data Analyst - Business Intelligence',
            'Machine Learning Engineer - Deep Learning'
        ];
        const companies = ['Google', 'Microsoft', 'Amazon', 'Apple', 'Meta', 'Netflix', 'Tesla', 'Nvidia', 'OpenAI', 'Anthropic'];
        const locations = [
            'Mountain View, CA', 'Seattle, WA', 'New York, NY', 'Austin, TX', 'San Francisco, CA',
            'Los Angeles, CA', 'Chicago, IL', 'Boston, MA', 'Denver, CO', 'Portland, OR'
        ];
        const countries = ['United States', 'Germany', 'Canada', 'United Kingdom', 'Australia', 'Netherlands', 'France', 'Brazil'];
        const scheduleTypes = ['Full-time', 'Part-time', 'Contractor', 'Temp work', 'Internship'];
        const skillSets = [
            '["python", "sql", "machine learning", "tensorflow", "aws"]',
            '["java", "spring", "microservices", "docker", "kubernetes"]',
            '["javascript", "react", "node.js", "mongodb", "graphql"]',
            '["python", "pandas", "numpy", "tableau", "powerbi"]',
            '["scala", "spark", "hadoop", "kafka", "elasticsearch"]'
        ];
        
        // 生成2000条模拟数据（而不是500条）
        return Array.from({ length: 2000 }, (_, i) => ({
            id: i + 1,
            job_title_short: jobTitles[i % jobTitles.length],
            job_title: fullTitles[i % fullTitles.length],
            company_name: companies[i % companies.length],
            job_location: locations[i % locations.length],
            job_country: countries[i % countries.length],
            job_schedule_type: scheduleTypes[i % scheduleTypes.length],
            salary_year_avg: 60000 + (i * 500) + Math.floor(Math.random() * 20000),
            job_posted_date: new Date(Date.now() - (i * 24 * 60 * 60 * 1000) - Math.floor(Math.random() * 30 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0],
            job_skills: skillSets[i % skillSets.length],
            job_work_from_home: Math.random() > 0.6 ? 1 : 0
        }));
    }
    
    applyFiltersToMockData(jobs) {
        return jobs.filter(job => {
            // 搜索筛选
            if (this.currentFilters.search) {
                const searchTerm = this.currentFilters.search.toLowerCase();
                const searchableText = [
                    job.job_title_short,
                    job.job_title,
                    job.company_name,
                    job.job_location,
                    job.job_skills
                ].join(' ').toLowerCase();
                
                if (!searchableText.includes(searchTerm)) {
                    return false;
                }
            }
            
            // 职位类型筛选 (使用job_title_short字段)
            if (this.currentFilters.job_type) {
                const jobType = job.job_title_short || job.job_title;
                if (!jobType.includes(this.currentFilters.job_type)) {
                    return false;
                }
            }
            
            // 国家筛选 (使用job_country字段)
            if (this.currentFilters.job_country && job.job_country !== this.currentFilters.job_country) {
                return false;
            }
            
            // 工作类型筛选 (使用job_schedule_type字段)
            if (this.currentFilters.job_schedule_type && job.job_schedule_type !== this.currentFilters.job_schedule_type) {
                return false;
            }
            
            // 远程工作筛选 (使用job_work_from_home字段)
            if (this.currentFilters.job_work_from_home !== undefined && this.currentFilters.job_work_from_home !== '') {
                const isRemote = this.currentFilters.job_work_from_home === 'true';
                if ((isRemote && job.job_work_from_home !== 1) || (!isRemote && job.job_work_from_home !== 0)) {
                    return false;
                }
            }
            
            // 薪资范围筛选
            if (this.currentFilters.salary_min && job.salary_year_avg < parseInt(this.currentFilters.salary_min)) {
                return false;
            }
            
            if (this.currentFilters.salary_max && job.salary_year_avg > parseInt(this.currentFilters.salary_max)) {
                return false;
            }
            
            return true;
        });
    }
    
    updatePagination(pagination) {
        this.currentPage = pagination.page;
        this.totalPages = pagination.total_pages;
        
        // 更新分页信息显示
        const elements = {
            currentPage: document.getElementById('currentPage'),
            totalPages: document.getElementById('totalPages'),
            totalJobs: document.querySelector('.pagination-info .total-info #totalJobs')
        };
        
        if (elements.currentPage) elements.currentPage.textContent = this.currentPage;
        if (elements.totalPages) elements.totalPages.textContent = this.totalPages;
        if (elements.totalJobs) elements.totalJobs.textContent = this.formatNumber(pagination.total_items);
        
        // 更新分页按钮状态
        this.updatePaginationButtons();
        
        // 生成页码
        this.generatePageNumbers();
    }
    
    updatePaginationButtons() {
        const buttons = {
            firstBtn: document.getElementById('firstBtn'),
            prevBtn: document.getElementById('prevBtn'),
            nextBtn: document.getElementById('nextBtn'),
            lastBtn: document.getElementById('lastBtn')
        };
        
        if (buttons.firstBtn) buttons.firstBtn.disabled = this.currentPage <= 1;
        if (buttons.prevBtn) buttons.prevBtn.disabled = this.currentPage <= 1;
        if (buttons.nextBtn) buttons.nextBtn.disabled = this.currentPage >= this.totalPages;
        if (buttons.lastBtn) buttons.lastBtn.disabled = this.currentPage >= this.totalPages;
    }
    
    generatePageNumbers() {
        const pageNumbers = document.getElementById('pageNumbers');
        if (!pageNumbers) return;
        
        pageNumbers.innerHTML = '';
        
        const range = 5;
        let start = Math.max(1, this.currentPage - Math.floor(range / 2));
        let end = Math.min(this.totalPages, start + range - 1);
        
        if (end - start < range - 1) {
            start = Math.max(1, end - range + 1);
        }
        
        for (let i = start; i <= end; i++) {
            const pageBtn = document.createElement('button');
            pageBtn.className = `page-number ${i === this.currentPage ? 'active' : ''}`;
            pageBtn.textContent = i;
            pageBtn.onclick = () => this.goToPage(i);
            pageNumbers.appendChild(pageBtn);
        }
    }
    
    goToPage(page) {
        if (page >= 1 && page <= this.totalPages && page !== this.currentPage) {
            this.currentPage = page;
            this.loadJobsTable();
        }
    }
    
    firstPage() { this.goToPage(1); }
    previousPage() { this.goToPage(this.currentPage - 1); }
    nextPage() { this.goToPage(this.currentPage + 1); }
    lastPage() { this.goToPage(this.totalPages); }
    
    changePageSize(newSize) {
        this.pageSize = parseInt(newSize);
        this.currentPage = 1;
        this.loadJobsTable();
    }
    
    // 新的标签选择函数
    selectFilter(filterType, value, element) {
        // 确保参数有效
        if (!filterType || !element) {
            console.error('selectFilter: Invalid parameters', {filterType, value, element});
            return;
        }
        
        // 移除同组中其他标签的active类
        const group = element.parentElement;
        if (group) {
            group.querySelectorAll('.filter-tag').forEach(tag => {
                tag.classList.remove('active');
            });
        }
        
        // 添加当前标签的active类
        element.classList.add('active');
        
        // 更新筛选器状态
        const filterMappings = {
            'jobType': 'job_type',
            'country': 'job_country', 
            'schedule': 'job_schedule_type',
            'remote': 'job_work_from_home'
        };
        
        const filterKey = filterMappings[filterType];
        if (filterKey) {
            // 确保currentFilters对象存在
            if (!this.currentFilters) {
                this.currentFilters = {};
            }
            
            if (value && value !== '') {
                this.currentFilters[filterKey] = value;
            } else {
                delete this.currentFilters[filterKey];
            }
        }
        
        this.currentPage = 1;
        this.loadJobsTable();
        this.updateActiveFilters();
        this.updateFilterCount();
        
        // 中文通知消息
        const filterTypeLabels = {
            'jobType': '职位类型',
            'country': '工作地点',
            'schedule': '工作类型',
            'remote': '远程工作'
        };
        
        const typeLabel = filterTypeLabels[filterType] || filterType;
        const message = (value && value !== '') ? `已应用筛选: ${typeLabel} - ${value}` : `已移除 ${typeLabel} 筛选`;
        this.showNotification(message);
    }

    applyTableFilters() {
        // 添加薪资范围筛选
        const salaryMin = document.getElementById('salaryMin')?.value || '';
        const salaryMax = document.getElementById('salaryMax')?.value || '';
        
        if (salaryMin) {
            this.currentFilters.salary_min = salaryMin;
        } else {
            delete this.currentFilters.salary_min;
        }
        
        if (salaryMax) {
            this.currentFilters.salary_max = salaryMax;
        } else {
            delete this.currentFilters.salary_max;
        }
        
        this.currentPage = 1;
        this.loadJobsTable();
        this.updateActiveFilters();
        this.updateFilterCount();
        
        this.showNotification('Salary filters applied');
    }
    
    resetTableFilters() {
        // 重置所有标签式筛选器
        const filterGroups = [
            'jobTypeFilters', 'countryFilters', 'scheduleFilters', 'remoteFilters'
        ];
        
        filterGroups.forEach(groupId => {
            const group = document.getElementById(groupId);
            if (group) {
                // 移除所有active类
                group.querySelectorAll('.filter-tag').forEach(tag => {
                    tag.classList.remove('active');
                });
                // 激活第一个标签（通常是"All"选项）
                const firstTag = group.querySelector('.filter-tag');
                if (firstTag) {
                    firstTag.classList.add('active');
                }
            }
        });
        
        // 重置输入框
        const inputElements = ['salaryMin', 'salaryMax', 'searchInput'];
        inputElements.forEach(id => {
            const element = document.getElementById(id);
            if (element) {
                element.value = '';
            }
        });
        
        this.currentFilters = {};
        this.currentPage = 1;
        this.loadJobsTable();
        this.updateActiveFilters();
        this.updateFilterCount();
        
        this.showNotification('已清除所有筛选条件');
    }
    
    searchJobs() {
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            const query = searchInput.value.trim();
            if (query) {
                this.currentFilters.search = query;
            } else {
                delete this.currentFilters.search;
            }
            this.currentPage = 1;
            this.loadJobsTable();
            this.updateActiveFilters();
            this.updateFilterCount();
        }
    }
    
    // 移除单个筛选条件
    removeFilter(filterKey) {
        delete this.currentFilters[filterKey];
        
        // 清空对应的输入控件
        const elementMappings = {
            job_type: 'jobTypeFilter',
            location: 'locationFilter',
            schedule_type: 'scheduleFilter',
            work_from_home: 'remoteFilter',
            salary_min: 'salaryMin',
            salary_max: 'salaryMax',
            search: 'searchInput'
        };
        
        const elementId = elementMappings[filterKey];
        if (elementId) {
            const element = document.getElementById(elementId);
            if (element) {
                element.value = '';
            }
        }
        
        this.currentPage = 1;
        this.loadJobsTable();
        this.updateActiveFilters();
        
        this.showNotification('筛选条件已移除');
    }
    
    sortTable(columnIndex) {
        this.showNotification('排序功能开发中...');
    }
    
    async viewJobDetails(jobId) {
        if (!jobId) {
            this.showNotification('岗位ID无效', 'error');
            return;
        }

        const modal = document.getElementById('jobDetailModal');
        const content = document.getElementById('jobDetailContent');
        
        // 显示模态框和加载状态
        modal.style.display = 'flex';
        setTimeout(() => modal.classList.add('show'), 10);
        
        // 显示加载状态
        content.innerHTML = `
            <div class="job-detail-loading">
                <i class="fas fa-spinner fa-spin"></i>
                <p>正在加载岗位详情...</p>
            </div>
        `;

        try {
            const response = await fetch(`${this.apiBaseUrl}/jobs/${jobId}`);
            const result = await response.json();

            if (!response.ok) {
                throw new Error(result.detail || '获取岗位详情失败');
            }

            const job = result.data;
            // 新增：记录当前职位索引与详情
            this.currentJobIndex = this.currentJobs.findIndex(j => String(j.id) === String(jobId));
            this.currentJobDetail = job;
            this.displayJobDetail(job);

        } catch (error) {
            console.error('获取岗位详情失败:', error);
            content.innerHTML = `
                <div class="job-detail-loading">
                    <i class="fas fa-exclamation-triangle" style="color: #ef4444;"></i>
                    <p style="color: #ef4444;">加载岗位详情失败: ${error.message}</p>
                    <button class="btn btn-secondary" onclick="jhDashboard.closeJobDetailModal()" style="margin-top: 16px;">
                        关闭
                    </button>
                </div>
            `;
        }
    }

    // 新增：上一条/下一条
    viewPrevJobDetail() {
        if (!Array.isArray(this.currentJobs) || this.currentJobs.length === 0) return;
        if (this.currentJobIndex <= 0) {
            this.showNotification('已经是当前页第一条', 'warning');
            return;
        }
        const prev = this.currentJobs[this.currentJobIndex - 1];
        if (prev && prev.id !== undefined) {
            this.viewJobDetails(prev.id);
        }
    }

    viewNextJobDetail() {
        if (!Array.isArray(this.currentJobs) || this.currentJobs.length === 0) return;
        if (this.currentJobIndex < 0) this.currentJobIndex = 0;
        if (this.currentJobIndex >= this.currentJobs.length - 1) {
            this.showNotification('已经是当前页最后一条', 'warning');
            return;
        }
        const next = this.currentJobs[this.currentJobIndex + 1];
        if (next && next.id !== undefined) {
            this.viewJobDetails(next.id);
        }
    }

    // 新增：复制到剪贴板
    async copyToClipboard(text) {
        try {
            if (navigator.clipboard && window.isSecureContext) {
                await navigator.clipboard.writeText(text);
            } else {
                const ta = document.createElement('textarea');
                ta.value = text;
                ta.style.position = 'fixed';
                ta.style.left = '-9999px';
                document.body.appendChild(ta);
                ta.focus();
                ta.select();
                document.execCommand('copy');
                ta.remove();
            }
            this.showNotification('已复制到剪贴板');
        } catch (e) {
            this.showNotification('复制失败', 'error');
        }
    }

    // 新增：生成职位摘要文本并复制
    copyJobSummary() {
        const job = this.currentJobDetail;
        if (!job) return;
        const skills = (() => {
            if (!job.job_skills) return [];
            if (Array.isArray(job.job_skills)) return job.job_skills;
            if (typeof job.job_skills === 'string') {
                try { return JSON.parse(job.job_skills); } catch { return job.job_skills.split(',').map(s => s.trim()).filter(Boolean); }
            }
            return [];
        })();
        const salary = job.salary_year_avg ? `$${Number(job.salary_year_avg).toLocaleString()}/年` : '面议';
        const summary = [
            `职位：${job.job_title_short || job.job_title || '未知'}`,
            `公司：${job.company_name || '未知'}`,
            `地点：${job.job_location || '未指定'} / ${job.job_country || ''}`,
            `类型：${job.job_schedule_type || '未指定'}；远程：${job.job_work_from_home == 1 ? '是' : '否'}`,
            `年薪：${salary}`,
            skills.length ? `技能：${skills.join(', ')}` : ''
        ].filter(Boolean).join('\n');
        this.copyToClipboard(summary);
    }

    // 新增：网页搜索（使用职位+公司）
    openJobSearch() {
        const job = this.currentJobDetail;
        if (!job) return;
        const q = encodeURIComponent(`${job.job_title_short || job.job_title || ''} ${job.company_name || ''}`.trim());
        const url = `https://www.google.com/search?q=${q}`;
        window.open(url, '_blank');
    }

    displayJobDetail(job) {
        const content = document.getElementById('jobDetailContent');
        const title = document.getElementById('jobDetailTitle');
        
        // 更新标题
        title.textContent = job.job_title_short || job.job_title || '岗位详情';

        // 处理技能数据
        let skills = [];
        if (job.job_skills) {
            if (Array.isArray(job.job_skills)) {
                skills = job.job_skills;
            } else if (typeof job.job_skills === 'string') {
                try {
                    skills = JSON.parse(job.job_skills);
                } catch {
                    skills = job.job_skills.split(',').map(s => s.trim()).filter(s => s);
                }
            }
        }

        // 格式化薪资
        const formatSalary = (salary) => {
            if (!salary) return '面议';
            if (typeof salary === 'number') {
                return `$${salary.toLocaleString()}/年`;
            }
            return salary;
        };

        // 格式化日期
        const formatDate = (dateStr) => {
            if (!dateStr) return '未知';
            try {
                return job.job_posted_date_formatted || this.formatDate(dateStr);
            } catch {
                return dateStr;
            }
        };

        // 新增：操作栏（复制、搜索、上一条、下一条）
        const actionBar = `
            <div class="job-detail-actions">
                <div class="left">
                    <button class="icon-btn" title="复制摘要 (C)" onclick="jhDashboard.copyJobSummary()"><i class="fas fa-copy"></i><span>复制摘要</span></button>
                    <button class="icon-btn" title="网页搜索 (G)" onclick="jhDashboard.openJobSearch()"><i class="fas fa-search"></i><span>网页搜索</span></button>
                </div>
                <div class="right">
                    <button class="icon-btn" title="上一条 (←)" onclick="jhDashboard.viewPrevJobDetail()"><i class="fas fa-arrow-left"></i><span>上一条</span></button>
                    <button class="icon-btn" title="下一条 (→)" onclick="jhDashboard.viewNextJobDetail()"><i class="fas fa-arrow-right"></i><span>下一条</span></button>
                </div>
            </div>`;

        // 渲染岗位详情
        content.innerHTML = `
            <div class="job-detail-content">
                <div class="job-detail-header">
                    <h2 class="job-title">${this.escapeHtml(job.job_title || job.job_title_short || '未知岗位')}</h2>
                    <div class="job-company">${this.escapeHtml(job.company_name || '未知公司')}</div>
                    ${actionBar}
                    <div class="job-meta-grid">
                        <div class="job-meta-item">
                            <i class="fas fa-map-marker-alt"></i>
                            <span>${this.escapeHtml(job.job_location || '未指定')}</span>
                        </div>
                        <div class="job-meta-item">
                            <i class="fas fa-briefcase"></i>
                            <span>${this.escapeHtml(job.job_schedule_type || '未指定')}</span>
                        </div>
                        <div class="job-meta-item">
                            <i class="fas fa-calendar-alt"></i>
                            <span>${formatDate(job.job_posted_date)}</span>
                        </div>
                        <div class="job-meta-item">
                            <i class="fas fa-globe"></i>
                            <span>${this.escapeHtml(job.job_country || '未指定')}</span>
                        </div>
                    </div>
                </div>

                <div class="job-detail-body">
                    <div class="job-info-grid">
                        <div class="job-info-item">
                            <div class="job-info-label">年薪</div>
                            <div class="job-info-value salary">${formatSalary(job.salary_year_avg)}</div>
                        </div>
                        <div class="job-info-item">
                            <div class="job-info-label">工作模式</div>
                            <div class="job-badges">
                                <span class="remote-badge ${job.job_work_from_home == 1 ? 'remote-yes' : 'remote-no'}" title="${job.job_work_from_home == 1 ? '远程工作' : '现场办公'}">
                                    <i class="fas ${job.job_work_from_home == 1 ? 'fa-home' : 'fa-building'}"></i>
                                    ${job.job_work_from_home == 1 ? '远程' : '现场'}
                                </span>
                                ${job.job_schedule_type ? `
                                <span class="schedule-badge"><i class="fas fa-briefcase"></i>${this.escapeHtml(job.job_schedule_type)}</span>
                                ` : ''}
                            </div>
                        </div>
                        <div class="job-info-item">
                            <div class="job-info-label">学历要求</div>
                            <div class="job-info-value">
                                ${job.job_no_degree_mention == 1 ? '无学历要求' : '有学历要求'}
                            </div>
                        </div>
                        <div class="job-info-item">
                            <div class="job-info-label">医疗保险</div>
                            <div class="job-info-value">
                                <i class="fas ${job.job_health_insurance == 1 ? 'fa-check-circle' : 'fa-times-circle'}"></i>
                                ${job.job_health_insurance == 1 ? '提供' : '不提供'}
                            </div>
                        </div>
                    </div>

                    ${job.job_via ? `
                        <details class="job-section" open>
                            <summary class="job-section-title">
                                <i class="fas fa-link"></i>
                                招聘来源
                            </summary>
                            <p class="job-description">${this.escapeHtml(job.job_via)}</p>
                        </details>
                    ` : ''}

                    ${skills.length > 0 ? `
                        <details class="job-section" open>
                            <summary class="job-section-title">
                                <i class="fas fa-tools"></i>
                                技能要求
                            </summary>
                            <div class="job-skills-grid">
                                ${skills.map(skill => 
                                    `<span class="job-skill-tag">${this.escapeHtml(skill)}</span>`
                                ).join('')}
                            </div>
                        </details>
                    ` : ''}

                    ${job.job_type_skills ? `
                        <details class="job-section">
                            <summary class="job-section-title">
                                <i class="fas fa-cogs"></i>
                                职位类型技能
                            </summary>
                            <p class="job-description">${this.escapeHtml(job.job_type_skills)}</p>
                        </details>
                    ` : ''}

                    ${job.search_location && job.search_location !== job.job_location ? `
                        <details class="job-section">
                            <summary class="job-section-title">
                                <i class="fas fa-search-location"></i>
                                搜索地区
                            </summary>
                            <p class="job-description">${this.escapeHtml(job.search_location)}</p>
                        </details>
                    ` : ''}

                    <details class="job-section" open>
                        <summary class="job-section-title">
                            <i class="fas fa-gift"></i>
                            福利待遇
                        </summary>
                        <div class="job-benefits">
                            ${job.job_work_from_home == 1 ? '<div class="job-benefit-tag"><i class="fas fa-home"></i>远程工作</div>' : ''}
                            ${job.job_health_insurance == 1 ? '<div class="job-benefit-tag"><i class="fas fa-heartbeat"></i>医疗保险</div>' : ''}
                            ${job.job_no_degree_mention == 1 ? '<div class="job-benefit-tag"><i class="fas fa-graduation-cap"></i>无学历要求</div>' : ''}
                            ${job.salary_year_avg ? `<div class=\"job-benefit-tag\"><i class=\"fas fa-dollar-sign\"></i>年薪 ${formatSalary(job.salary_year_avg)}</div>` : ''}
                        </div>
                    </details>
                </div>
            </div>
        `;
    }

    closeJobDetailModal() {
        const modal = document.getElementById('jobDetailModal');
        modal.classList.remove('show');
        setTimeout(() => {
            modal.style.display = 'none';
        }, 400);
    }

    // 初始化岗位详情模态框事件监听
    initJobDetailModal() {
        const modal = document.getElementById('jobDetailModal');
        
        // 点击背景关闭模态框
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                this.closeJobDetailModal();
            }
        });

        // ESC/左右方向键
        document.addEventListener('keydown', (e) => {
            const isOpen = modal.style.display === 'flex';
            if (!isOpen) return;
            if (e.key === 'Escape') {
                this.closeJobDetailModal();
            } else if (e.key === 'ArrowLeft') {
                this.viewPrevJobDetail();
            } else if (e.key === 'ArrowRight') {
                this.viewNextJobDetail();
            } else if (e.key.toLowerCase() === 'c') {
                this.copyJobSummary();
            } else if (e.key.toLowerCase() === 'g') {
                this.openJobSearch();
            }
        });
    }
    
    exportData() {
        this.showNotification('数据导出功能开发中...');
    }
    
    escapeHtml(text) {
        const map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };
        return text ? text.replace(/[&<>"']/g, m => map[m]) : '';
    }
    
    // 删除翻译函数，直接显示原始英文数据
    
    formatDate(dateString) {
        if (!dateString) return 'N/A';
        try {
            const date = new Date(dateString);
            return date.toLocaleDateString('zh-CN');
        } catch {
            return dateString;
        }
    }
    
    formatSkills(skillsString) {
        if (!skillsString) return 'N/A';
        try {
            const skills = JSON.parse(skillsString);
            if (Array.isArray(skills)) {
                return skills.slice(0, 3).map(skill => 
                    `<span class="skill-tag">${this.escapeHtml(skill)}</span>`
                ).join(' ');
            }
        } catch {
            // 如果不是JSON格式，直接显示
        }
        return this.escapeHtml(skillsString.substring(0, 50) + (skillsString.length > 50 ? '...' : ''));
    }
    
    // 初始化模态框
    initializeModal() {
        const modal = document.getElementById('chartModal');
        const closeBtn = document.getElementById('closeModal');
        const modalRefreshBtn = document.getElementById('modalRefreshBtn');
        const modalChartTypeSelect = document.getElementById('modalChartTypeSelect');
        const modalDimensionSelect = document.getElementById('modalDimensionSelect');
        
        // 关闭模态框事件
        closeBtn.addEventListener('click', () => this.closeChartModal());
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                this.closeChartModal();
            }
        });
        
        // 全局键盘快捷键
        document.addEventListener('keydown', (e) => {
            // ESC键关闭模态框
            if (e.key === 'Escape' && modal.classList.contains('show')) {
                this.closeChartModal();
            }
            // F5 快捷键刷新所有图表
            if (e.key === 'F5') {
                e.preventDefault();
                this.resizeAllCharts();
                this.showNotification('图表已刷新调整', 'success');
            }
            
            // 模态框专用快捷键
            if (modal.classList.contains('show')) {
                switch (e.key) {
                    case 'f':
                    case 'F':
                        if (e.ctrlKey || e.metaKey) {
                            e.preventDefault();
                            this.toggleModalFullscreen();
                        }
                        break;
                    case 'd':
                    case 'D':
                        if (e.ctrlKey || e.metaKey) {
                            e.preventDefault();
                            this.downloadModalChart();
                        }
                        break;
                    case 't':
                    case 'T':
                        if (e.ctrlKey || e.metaKey) {
                            e.preventDefault();
                            this.toggleChartDataView();
                        }
                        break;
                    case 'r':
                    case 'R':
                        if (e.ctrlKey || e.metaKey) {
                            e.preventDefault();
                            this.refreshModalChart();
                        }
                        break;
                    case 'z':
                    case 'Z':
                        if (e.ctrlKey || e.metaKey) {
                            e.preventDefault();
                            this.resetChartZoom();
                        }
                        break;
                }
            }
        });
        
        // 模态框内控件事件
        modalRefreshBtn.addEventListener('click', () => {
            if (this.currentModalChartId) {
                this.refreshModalChart();
            }
        });
        
        modalChartTypeSelect.addEventListener('change', () => {
            if (this.currentModalChartId) {
                this.refreshModalChart();
            }
        });
        
        modalDimensionSelect.addEventListener('change', () => {
            if (this.currentModalChartId) {
                this.refreshModalChart();
            }
        });
    }
    
    // 打开图表模态框
    async openChartModal(chartId) {
        const modal = document.getElementById('chartModal');
        if (!modal) return;
        
        this.currentModalChartId = chartId;
        
        // 更新模态框标题
        const modalTitle = document.getElementById('modalChartTitle');
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        const chartTitle = chartCard ? chartCard.querySelector('.chart-title').textContent : '图表详情';
        modalTitle.innerHTML = `<i class="fas fa-chart-bar"></i> ${chartTitle}`;
        
        // 设置维度选择器选项
        this.updateModalDimensionOptions(chartId);
        
        // 设置当前图表ID到服务端
        await this.setCurrentChartOnServer(chartId);
        
        // 显示模态框
        modal.style.display = 'flex';
        setTimeout(() => {
            modal.classList.add('show');
        }, 10);
        
        // 绑定事件监听器
        this.bindModalEventListeners();
        
        // 绑定帮助模态框事件
        this.bindHelpModalEvents();
        
        // 显示加载状态
        this.showModalLoading(true);
        
        // 加载图表数据
        await this.refreshModalChart();
        
        // 隐藏加载状态
        this.showModalLoading(false);
        
        // 确保图表在模态框显示后正确调整大小
        setTimeout(() => {
            if (this.modalChart) {
                this.modalChart.resize();
            }
        }, 400);
    }
    
    // 关闭图表模态框
    closeChartModal() {
        const modal = document.getElementById('chartModal');
        if (!modal) return;
        
        // 添加关闭动画类
        modal.classList.add('closing');
        modal.classList.remove('show');
        
        setTimeout(() => {
            modal.style.display = 'none';
            modal.classList.remove('closing', 'fullscreen');
            
            // 隐藏缩放提示
            const zoomHint = document.getElementById('zoomHint');
            if (zoomHint) {
                zoomHint.style.display = 'none';
            }
            
            // 销毁图表实例
            if (this.modalChart) {
                this.modalChart.destroy();
                this.modalChart = null;
            }

            // 隐藏AI聊天面板
            this.hideAIChat();

            this.currentModalChartId = null;
            this.unbindModalEventListeners();
        }, 300);
    }
    
    // 绑定模态框事件监听器
    bindModalEventListeners() {
        // 避免重复绑定
        this.unbindModalEventListeners();
        
        // 关闭按钮
        this.closeModalHandler = () => this.closeChartModal();
        document.getElementById('closeModal').addEventListener('click', this.closeModalHandler);
        
        // 全屏切换
        this.toggleFullscreenHandler = () => this.toggleModalFullscreen();
        document.getElementById('toggleFullscreen').addEventListener('click', this.toggleFullscreenHandler);
        
        // 下载图表
        this.downloadChartHandler = () => this.downloadModalChart();
        document.getElementById('downloadChart').addEventListener('click', this.downloadChartHandler);
        
        // 刷新图表
        this.modalRefreshHandler = () => this.refreshModalChart();
        document.getElementById('modalRefreshBtn').addEventListener('click', this.modalRefreshHandler);
        
        // 重置缩放
        this.resetZoomHandler = () => this.resetChartZoom();
        document.getElementById('resetZoomBtn').addEventListener('click', this.resetZoomHandler);
        
        // 数据表格切换
        this.toggleDataViewHandler = () => this.toggleChartDataView();
        document.getElementById('toggleDataView').addEventListener('click', this.toggleDataViewHandler);
        
        // 导出数据
        this.exportDataHandler = () => this.exportChartData();
        document.getElementById('exportDataBtn').addEventListener('click', this.exportDataHandler);
        
        // AI聊天切换
        this.toggleAIChatHandler = () => this.toggleAIChat();
        document.getElementById('toggleAIChat').addEventListener('click', this.toggleAIChatHandler);
        
        // 关闭AI聊天
        this.closeAIChatHandler = () => this.hideAIChat();
        document.getElementById('closeAIChat').addEventListener('click', this.closeAIChatHandler);
        
        // 显示帮助
        this.showHelpHandler = () => this.showHelpModal();
        document.getElementById('showHelp').addEventListener('click', this.showHelpHandler);
        
        // 图表类型选择
        this.chartTypeChangeHandler = () => this.refreshModalChart();
        document.getElementById('modalChartTypeSelect').addEventListener('change', this.chartTypeChangeHandler);
        
        // 维度选择
        this.dimensionChangeHandler = () => this.refreshModalChart();
        document.getElementById('modalDimensionSelect').addEventListener('change', this.dimensionChangeHandler);
        
        // 图表尺寸控制
        this.sizeControlHandler = (e) => {
            if (e.target.classList.contains('size-preset-btn')) {
                this.changeChartSize(e.target.dataset.size);
            }
        };
        document.querySelector('.chart-size-controls').addEventListener('click', this.sizeControlHandler);
        
        // ESC键关闭
        this.escKeyHandler = (e) => {
            if (e.key === 'Escape') {
                this.closeChartModal();
            }
        };
        document.addEventListener('keydown', this.escKeyHandler);
        
        // 点击背景关闭
        this.backdropClickHandler = (e) => {
            if (e.target.id === 'chartModal') {
                this.closeChartModal();
            }
        };
        document.getElementById('chartModal').addEventListener('click', this.backdropClickHandler);
    }
    
    // 解绑模态框事件监听器
    unbindModalEventListeners() {
        if (this.closeModalHandler) {
            document.getElementById('closeModal').removeEventListener('click', this.closeModalHandler);
        }
        if (this.toggleFullscreenHandler) {
            document.getElementById('toggleFullscreen').removeEventListener('click', this.toggleFullscreenHandler);
        }
        if (this.downloadChartHandler) {
            document.getElementById('downloadChart').removeEventListener('click', this.downloadChartHandler);
        }
        if (this.modalRefreshHandler) {
            document.getElementById('modalRefreshBtn').removeEventListener('click', this.modalRefreshHandler);
        }
        if (this.resetZoomHandler) {
            document.getElementById('resetZoomBtn').removeEventListener('click', this.resetZoomHandler);
        }
        if (this.toggleDataViewHandler) {
            document.getElementById('toggleDataView').removeEventListener('click', this.toggleDataViewHandler);
        }
        if (this.exportDataHandler) {
            document.getElementById('exportDataBtn').removeEventListener('click', this.exportDataHandler);
        }
        if (this.toggleAIChatHandler) {
            document.getElementById('toggleAIChat').removeEventListener('click', this.toggleAIChatHandler);
        }
        if (this.closeAIChatHandler) {
            document.getElementById('closeAIChat').removeEventListener('click', this.closeAIChatHandler);
        }
        if (this.showHelpHandler) {
            document.getElementById('showHelp').removeEventListener('click', this.showHelpHandler);
        }
        if (this.chartTypeChangeHandler) {
            document.getElementById('modalChartTypeSelect').removeEventListener('change', this.chartTypeChangeHandler);
        }
        if (this.dimensionChangeHandler) {
            document.getElementById('modalDimensionSelect').removeEventListener('change', this.dimensionChangeHandler);
        }
        if (this.sizeControlHandler) {
            const sizeControls = document.querySelector('.chart-size-controls');
            if (sizeControls) {
                sizeControls.removeEventListener('click', this.sizeControlHandler);
            }
        }
        if (this.escKeyHandler) {
            document.removeEventListener('keydown', this.escKeyHandler);
        }
        if (this.backdropClickHandler) {
            const modal = document.getElementById('chartModal');
            if (modal) {
                modal.removeEventListener('click', this.backdropClickHandler);
            }
        }
    }
    
    // 切换全屏模式
    toggleModalFullscreen() {
        const modal = document.getElementById('chartModal');
        const fullscreenBtn = document.getElementById('toggleFullscreen');
        const icon = fullscreenBtn.querySelector('i');
        
        modal.classList.toggle('fullscreen');
        
        if (modal.classList.contains('fullscreen')) {
            icon.className = 'fas fa-compress';
            fullscreenBtn.title = '退出全屏';
        } else {
            icon.className = 'fas fa-expand';
            fullscreenBtn.title = '全屏模式';
        }
        
        // 调整图表大小
        setTimeout(() => {
            if (this.modalChart) {
                this.modalChart.resize();
            }
        }, 100);
    }
    
    // 下载图表
    downloadModalChart() {
        if (!this.modalChart) return;
        
        try {
            const canvas = this.modalChart.canvas;
            const chartTitle = document.getElementById('modalChartTitle').textContent.replace(/^\s*\S+\s*/, ''); // 移除图标
            
            // 创建临时链接下载
            const link = document.createElement('a');
            link.download = `${chartTitle}_${new Date().toISOString().slice(0, 10)}.png`;
            link.href = canvas.toDataURL('image/png', 1.0);
            link.click();
            
            this.showNotification('图表已下载', 'success');
        } catch (error) {
            console.error('下载图表失败:', error);
            this.showNotification('下载失败，请重试', 'error');
        }
    }
    
    // 切换数据表格视图
    toggleChartDataView() {
        const chartCanvas = document.getElementById('modalChart');
        const dataTable = document.getElementById('chartDataTable');
        const toggleBtn = document.getElementById('toggleDataView');
        const icon = toggleBtn.querySelector('i');
        
        const isShowingTable = dataTable.classList.contains('show');
        
        if (isShowingTable) {
            // 显示图表
            dataTable.classList.remove('show');
            chartCanvas.style.display = 'block';
            icon.className = 'fas fa-table';
            toggleBtn.innerHTML = '<i class="fas fa-table"></i> 数据表格';
        } else {
            // 显示表格
            this.generateChartDataTable();
            dataTable.classList.add('show');
            chartCanvas.style.display = 'none';
            icon.className = 'fas fa-chart-bar';
            toggleBtn.innerHTML = '<i class="fas fa-chart-bar"></i> 图表视图';
        }
    }
    
    // 生成图表数据表格
    generateChartDataTable() {
        if (!this.modalChart || !this.modalChart.data) return;
        
        const data = this.modalChart.data;
        const table = document.getElementById('chartDataTableContent');
        const thead = table.querySelector('thead tr');
        const tbody = table.querySelector('tbody');
        
        // 清空现有内容
        thead.innerHTML = '';
        tbody.innerHTML = '';
        
        // 生成表头
        const headerRow = document.createElement('tr');
        headerRow.innerHTML = '<th>项目</th><th>数值</th><th>百分比</th>';
        thead.appendChild(headerRow);
        
        // 计算总值用于百分比计算
        const total = data.datasets[0]?.data?.reduce((sum, val) => sum + val, 0) || 0;
        
        // 生成表格内容
        data.labels?.forEach((label, index) => {
            const value = data.datasets[0]?.data[index] || 0;
            const percentage = total > 0 ? ((value / total) * 100).toFixed(1) : '0.0';
            
            const row = document.createElement('tr');
            row.innerHTML = `
                <td>${label}</td>
                <td>${value.toLocaleString()}</td>
                <td>${percentage}%</td>
            `;
            tbody.appendChild(row);
        });
    }
    
    // 导出图表数据
    exportChartData() {
        if (!this.modalChart || !this.modalChart.data) return;
        
        try {
            const data = this.modalChart.data;
            const csvContent = this.convertChartDataToCSV(data);
            const chartTitle = document.getElementById('modalChartTitle').textContent.replace(/^\s*\S+\s*/, '');
            
            const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = `${chartTitle}_数据_${new Date().toISOString().slice(0, 10)}.csv`;
            link.click();
            
            this.showNotification('数据已导出', 'success');
        } catch (error) {
            console.error('导出数据失败:', error);
            this.showNotification('导出失败，请重试', 'error');
        }
    }
    
    // 将图表数据转换为CSV格式
    convertChartDataToCSV(data) {
        const headers = ['项目', '数值'];
        const rows = [headers.join(',')];
        
        data.labels?.forEach((label, index) => {
            const value = data.datasets[0]?.data[index] || 0;
            rows.push(`"${label}",${value}`);
        });
        
        return rows.join('\n');
    }
    
    // AI聊天相关方法
    toggleAIChat() {
        const rightPanel = document.getElementById('chartModalRightPanel');
        const toggleBtn = document.getElementById('toggleAIChat');
        
        if (rightPanel.classList.contains('show')) {
            this.hideAIChat();
        } else {
            this.showAIChat();
        }
    }
    
    showAIChat() {
        const rightPanel = document.getElementById('chartModalRightPanel');
        const toggleBtn = document.getElementById('toggleAIChat');
        
        rightPanel.classList.add('show');
        
        // 更新按钮状态
        if (toggleBtn) {
            toggleBtn.innerHTML = '<i class="fas fa-robot"></i> 隐藏AI';
            toggleBtn.classList.add('active');
        }
        
        // 初始化分割条拖拽功能
        initializeSplitter();
        
        // 聚焦到输入框
        setTimeout(() => {
            const input = document.getElementById('aiChatInput');
            if (input) input.focus();
        }, 300);
    }
    
    hideAIChat() {
        const rightPanel = document.getElementById('chartModalRightPanel');
        const toggleBtn = document.getElementById('toggleAIChat');
        const leftPanel = document.getElementById('chartModalLeftPanel');
        
        rightPanel.classList.remove('show');
        
        // 重置左栏宽度为100%
        if (leftPanel) {
            leftPanel.style.width = '100%';
        }
        
        // 更新按钮状态
        if (toggleBtn) {
            toggleBtn.innerHTML = '<i class="fas fa-robot"></i> AI分析';
            toggleBtn.classList.remove('active');
        }
    }
    
    // 绑定帮助模态框事件
    bindHelpModalEvents() {
        // 避免重复绑定
        this.unbindHelpModalEvents();
        
        // 关闭帮助按钮
        this.closeHelpHandler = () => this.closeHelpModal();
        document.getElementById('closeHelp').addEventListener('click', this.closeHelpHandler);
        
        // 点击背景关闭帮助
        this.helpBackdropClickHandler = (e) => {
            if (e.target.id === 'helpModal') {
                this.closeHelpModal();
            }
        };
        document.getElementById('helpModal').addEventListener('click', this.helpBackdropClickHandler);
    }
    
    // 解绑帮助模态框事件
    unbindHelpModalEvents() {
        if (this.closeHelpHandler) {
            const closeBtn = document.getElementById('closeHelp');
            if (closeBtn) {
                closeBtn.removeEventListener('click', this.closeHelpHandler);
            }
        }
        if (this.helpBackdropClickHandler) {
            const helpModal = document.getElementById('helpModal');
            if (helpModal) {
                helpModal.removeEventListener('click', this.helpBackdropClickHandler);
            }
        }
    }
    
    // 显示帮助模态框
    showHelpModal() {
        const helpModal = document.getElementById('helpModal');
        if (!helpModal) return;
        
        helpModal.style.display = 'flex';
        setTimeout(() => {
            helpModal.classList.add('show');
        }, 10);
    }
    
    // 关闭帮助模态框
    closeHelpModal() {
        const helpModal = document.getElementById('helpModal');
        if (!helpModal) return;
        
        helpModal.classList.remove('show');
        setTimeout(() => {
            helpModal.style.display = 'none';
        }, 300);
    }
    
    // 获取缩放配置
    getZoomConfig(chartType) {
        const baseConfig = {
            zoom: {
                wheel: {
                    enabled: true,
                    speed: 0.1
                },
                pinch: {
                    enabled: true
                },
                mode: 'xy',
                threshold: 2,
                sensitivity: 3,
                // 保持坐标轴标签和刻度的可见性
                onZoomRejected: function(chart, event) {
                    console.log('缩放被拒绝', event);
                },
                onZoomComplete: function(chart) {
                    // 缩放完成后保持坐标轴的显示
                    chart.update('none');
                }
            },
            pan: {
                enabled: true,
                mode: 'xy',
                threshold: 10,
                speed: 20,
                modifierKey: null,
                onPanComplete: function(chart) {
                    // 平移完成后保持坐标轴的显示
                    chart.update('none');
                }
            }
        };

        // 根据图表类型优化缩放行为
        switch (chartType) {
            case 'pie':
            case 'doughnut':
                // 饼图只允许缩放，不允许平移
                return {
                    zoom: {
                        ...baseConfig.zoom,
                        mode: 'xy'
                    },
                    pan: {
                        enabled: false
                    }
                };
            
            case 'line':
            case 'area':
                // 线图和面积图优化x轴缩放，保持坐标轴标签显示
                return {
                    ...baseConfig,
                    zoom: {
                        ...baseConfig.zoom,
                        mode: 'xy'
                    },
                    pan: {
                        ...baseConfig.pan,
                        mode: 'xy'
                    },
                    limits: {
                        x: {min: 'original', max: 'original'},
                        y: {min: 'original', max: 'original'}
                    }
                };
            
            case 'bar':
            case 'horizontalBar':
                // 柱状图允许双轴缩放
                return {
                    ...baseConfig,
                    limits: {
                        x: {min: 'original', max: 'original'},
                        y: {min: 0, max: 'original'}
                    }
                };
            
            case 'scatter':
            case 'bubble':
                // 散点图和气泡图允许完全自由缩放
                return baseConfig;
            
            default:
                return {
                    ...baseConfig,
                    limits: {
                        x: {min: 'original', max: 'original'},
                        y: {min: 0, max: 'original'}
                    }
                };
        }
    }
    
    // 重置图表缩放
    resetChartZoom() {
        if (!this.modalChart) {
            this.showNotification('没有可重置的图表', 'warning');
            return;
        }
        
        try {
            // 重置缩放
            this.modalChart.resetZoom();
            this.showNotification('已重置图表缩放', 'success');
        } catch (error) {
            console.error('重置缩放失败:', error);
            this.showNotification('重置缩放失败', 'error');
        }
    }
    
    // 缩放提示方法已移除
    
    // 增强的错误恢复机制
    async recoverFromChartError() {
        if (!this.currentModalChartId) return;
        
        try {
            this.showNotification('正在尝试恢复图表...', 'info');
            
            // 清理旧的图表实例
            if (this.modalChart) {
                try {
                    this.modalChart.destroy();
                } catch (e) {
                    console.warn('销毁图表时出现错误:', e);
                }
                this.modalChart = null;
            }
            
            // 清理canvas元素
            const canvas = document.getElementById('modalChart');
            if (canvas) {
                const parent = canvas.parentNode;
                const newCanvas = document.createElement('canvas');
                newCanvas.id = 'modalChart';
                newCanvas.style.width = '100%';
                newCanvas.style.height = '100%';
                parent.removeChild(canvas);
                parent.appendChild(newCanvas);
            }
            
            // 重新创建图表
            await this.refreshModalChart();
            
            this.showNotification('图表已恢复', 'success');
        } catch (error) {
            console.error('图表恢复失败:', error);
            this.showNotification('图表恢复失败，请刷新页面', 'error');
        }
    }
    
    // 更改图表尺寸
    changeChartSize(size) {
        const container = document.getElementById('chartModalContainer');
        const buttons = document.querySelectorAll('.size-preset-btn');
        
        // 更新按钮状态
        buttons.forEach(btn => btn.classList.remove('active'));
        document.querySelector(`[data-size="${size}"]`).classList.add('active');
        
        // 调整容器高度
        switch (size) {
            case 'small':
                container.style.minHeight = '400px';
                break;
            case 'medium':
                container.style.minHeight = '500px';
                break;
            case 'large':
                container.style.minHeight = '650px';
                break;
        }
        
        // 调整图表大小
        setTimeout(() => {
            if (this.modalChart) {
                this.modalChart.resize();
            }
        }, 100);
    }
    
    // 显示/隐藏模态框加载状态
    showModalLoading(show) {
        const loadingEl = document.getElementById('chartModalLoading');
        if (loadingEl) {
            loadingEl.style.display = show ? 'flex' : 'none';
        }
    }
    
    // 更新模态框维度选择器选项
    updateModalDimensionOptions(chartId) {
        const modalDimensionSelect = document.getElementById('modalDimensionSelect');
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        const originalSelect = chartCard?.querySelector('.dimension-select');
        
        if (originalSelect && modalDimensionSelect) {
            modalDimensionSelect.innerHTML = originalSelect.innerHTML;
            modalDimensionSelect.value = originalSelect.value;
        }
    }
    
    // 刷新模态框中的图表
    async refreshModalChart() {
        if (!this.currentModalChartId) return;
        
        const modalChartTypeSelect = document.getElementById('modalChartTypeSelect');
        const modalDimensionSelect = document.getElementById('modalDimensionSelect');
        const chartType = modalChartTypeSelect.value;
        const dimension = modalDimensionSelect.value;
        
        this.showModalLoading(true);
        
        try {
            // 销毁旧图表
            if (this.modalChart) {
                this.modalChart.destroy();
            }
            
            // 获取图表数据
            const response = await fetch(`${this.apiBaseUrl}/chart-data/${this.currentModalChartId}?dimension=${dimension}&expanded=true`);
            const chartData = await response.json();
            
            // 创建新图表
            const canvas = document.getElementById('modalChart');
            const ctx = canvas.getContext('2d');
            
            const config = this.createChartConfig(chartType, chartData, {
                responsive: true,
                maintainAspectRatio: false,
                interaction: {
                    intersect: false,
                    mode: 'index'
                },
                plugins: {
                    legend: {
                        position: 'bottom',
                        labels: {
                            usePointStyle: true,
                            padding: 20,
                            font: {
                                size: 13
                            }
                        }
                    },
                    tooltip: {
                        backgroundColor: 'rgba(0, 0, 0, 0.8)',
                        titleColor: 'white',
                        bodyColor: 'white',
                        borderColor: '#667eea',
                        borderWidth: 1,
                        cornerRadius: 8,
                        displayColors: true,
                        titleFont: {
                            size: 14,
                            weight: 'bold'
                        },
                        bodyFont: {
                            size: 13
                        }
                    },
                    // 添加拖拽缩放插件
                    zoom: this.getZoomConfig(chartType)
                },
                animation: {
                    duration: 1000,
                    easing: 'easeInOutQuart'
                }
            });
            
            this.modalChart = new Chart(ctx, config);
            
            // 缩放提示已移除
            
        } catch (error) {
            console.error('刷新模态框图表失败:', error);
            this.showNotification('加载图表失败，正在尝试恢复...', 'warning');
            
            // 尝试错误恢复
            try {
                await this.recoverFromChartError();
            } catch (recoveryError) {
                console.error('图表恢复也失败了:', recoveryError);
                this.showNotification('图表无法恢复，请刷新页面', 'error');
            }
        } finally {
            this.showModalLoading(false);
        }
    }
    
    // 新增：切换图表展开状态
    async toggleChartExpanded(chartId) {
        try {
            // 切换展开状态
            if (this.expandedCharts.has(chartId)) {
                this.expandedCharts.delete(chartId);
            } else {
                this.expandedCharts.add(chartId);
            }
            const expanded = this.expandedCharts.has(chartId);
            
            console.log(`${chartId} 展开状态: ${expanded}`);
            
            // 更新按钮状态和视觉效果
            this.updateExpandButton(chartId, expanded);
            
            // 重新获取数据（根据展开状态可能显示不同数量的数据）
            await this.refreshChart(chartId, expanded);
            
            // 添加平滑滚动到展开的图表
            if (expanded) {
                const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
                if (chartCard) {
                    setTimeout(() => {
                        chartCard.scrollIntoView({ 
                            behavior: 'smooth', 
                            block: 'center' 
                        });
                    }, 300); // 等待动画完成
                }
            }
            
        } catch (error) {
            console.error(`切换${chartId}展开状态失败:`, error);
        }
    }
    
    // 新增：更新图表函数，确保正确渲染
    updateChart(chartId, data, chartType, dimension) {
        const canvas = document.getElementById(chartId);
        if (!canvas) {
            console.warn(`画布元素不存在: ${chartId}`);
            return;
        }
        
        const ctx = canvas.getContext('2d');
        
        // 销毁现有图表
        if (this.charts[chartId]) {
            this.charts[chartId].destroy();
        }
        
        // 创建新图表配置
        const config = this.createChartConfig(chartType, data, dimension);
        
        // 创建新图表
        this.charts[chartId] = new Chart(ctx, config);
        
        // 更新数据量指示器
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        if (chartCard) {
            const itemCount = data.labels ? data.labels.length : 0;
            chartCard.setAttribute('data-items', itemCount);
        }
        
        // 同步表头选择器状态
        this.syncChartControls(chartId, chartType, dimension);
    }
    
    // 同步图表控件状态
    syncChartControls(chartId, chartType, dimension) {
        const chartCard = document.querySelector(`[data-chart-id="${chartId}"]`);
        if (!chartCard) return;
        
        // 同步图表类型选择器
        const typeSelect = chartCard.querySelector('.chart-type-select');
        if (typeSelect && typeSelect.value !== chartType) {
            typeSelect.value = chartType;
        }
        
        // 同步维度选择器
        const dimensionSelect = chartCard.querySelector('.dimension-select');
        if (dimensionSelect && dimensionSelect.value !== dimension) {
            dimensionSelect.value = dimension;
        }
        
        // 更新图表标题
        this.updateChartTitle(chartId, dimension);
    }
    
    // 同步所有图表控件状态
    syncAllChartControls() {
        const chartIds = ['jobTypeChart', 'locationChart', 'salaryChart', 'timeChart', 'skillsChart', 'companyChart'];
        
        chartIds.forEach(chartId => {
            const config = this.userPreferences.chartConfigs[chartId];
            if (config) {
                this.syncChartControls(chartId, config.type, config.dimension);
            }
        });
    }
    
    // 新增：创建图表配置
    createChartConfig(type, data, dimensionOrOptions) {
        // 判断第三个参数是字符串还是对象
        let dimension = null;
        let customOptions = {};
        
        if (typeof dimensionOrOptions === 'string') {
            dimension = dimensionOrOptions;
        } else if (typeof dimensionOrOptions === 'object' && dimensionOrOptions !== null) {
            customOptions = dimensionOrOptions;
        }
        
        const commonOptions = {
            responsive: true,
            maintainAspectRatio: false,
            interaction: {
                intersect: false,
                mode: 'index'
            },
            plugins: {
                legend: {
                    position: 'top',
                    labels: {
                        padding: 10,
                        usePointStyle: true,
                        font: {
                            size: 12
                        }
                    }
                },
                title: {
                    display: false
                },
                tooltip: {
                    backgroundColor: 'rgba(0, 0, 0, 0.8)',
                    titleColor: 'white',
                    bodyColor: 'white',
                    borderColor: 'rgba(255, 255, 255, 0.2)',
                    borderWidth: 1,
                    cornerRadius: 6,
                    displayColors: true
                },
                zoom: this.getZoomConfig(type)
            },
            layout: {
                padding: {
                    top: 10,
                    right: 10,
                    bottom: 10,
                    left: 10
                }
            },
            animation: {
                duration: 1000,
                easing: 'easeInOutQuart'
            },
            scales: {
                x: {
                    display: true,
                    grid: {
                        display: true
                    },
                    ticks: {
                        display: true,
                        maxRotation: 45,
                        minRotation: 0
                    }
                },
                y: {
                    display: true,
                    grid: {
                        display: true
                    },
                    ticks: {
                        display: true
                    }
                }
            }
        };
        
        // 合并自定义选项
        const mergedOptions = this.deepMerge(commonOptions, customOptions);
        
        const config = {
            type: type,
            data: {
                labels: data.labels || [],
                datasets: [{
                    data: data.values || [],
                    backgroundColor: this.getChartColors(data.labels?.length || 0),
                    borderColor: this.getChartColors(data.labels?.length || 0, 0.8),
                    borderWidth: 1,
                    hoverBackgroundColor: this.getChartColors(data.labels?.length || 0, 0.9),
                    hoverBorderColor: this.getChartColors(data.labels?.length || 0, 1),
                    hoverBorderWidth: 2
                }]
            },
            options: mergedOptions
        };
        
        // 根据图表类型调整配置
        if (type === 'horizontalBar') {
            config.type = 'bar';
            config.options.indexAxis = 'y';
            config.options.plugins.legend.position = 'top';
        } else if (type === 'doughnut' || type === 'pie') {
            config.options.plugins.legend.position = 'right';
            config.options.layout.padding = 20;
            // 饼图和环形图不需要坐标轴
            delete config.options.scales;
        } else if (type === 'line') {
            config.data.datasets[0].fill = false;
            config.data.datasets[0].tension = 0.4;
            config.data.datasets[0].pointBackgroundColor = this.getChartColors(1)[0];
            config.data.datasets[0].pointBorderColor = '#fff';
            config.data.datasets[0].pointBorderWidth = 2;
            config.data.datasets[0].pointRadius = 4;
            config.data.datasets[0].pointHoverRadius = 6;
        }
        
        return config;
    }
    
    // 深度合并对象
    deepMerge(target, source) {
        const result = { ...target };
        
        for (const key in source) {
            if (source.hasOwnProperty(key)) {
                if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
                    result[key] = this.deepMerge(result[key] || {}, source[key]);
                } else {
                    result[key] = source[key];
                }
            }
        }
        
        return result;
    }
    
    // 新增：初始化窗口大小变化监听器
    initializeResizeHandler() {
        let resizeTimeout;
        window.addEventListener('resize', () => {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(() => {
                this.resizeAllCharts();
            }, 300);
        });
    }
    
    // 新增：调整所有图表大小
    resizeAllCharts() {
        Object.keys(this.charts).forEach(chartId => {
            if (this.charts[chartId]) {
                try {
                    this.charts[chartId].resize();
                } catch (error) {
                    console.warn(`图表 ${chartId} 调整大小失败:`, error);
                }
            }
        });
        
        // 如果模态框中有图表，也要调整
        if (this.modalChart) {
            try {
                this.modalChart.resize();
            } catch (error) {
                console.warn('模态框图表调整大小失败:', error);
            }
        }
    }
    
    // 新增：获取图表颜色
    getChartColors(count, alpha = 0.7) {
        const colors = [
            `rgba(255, 99, 132, ${alpha})`,
            `rgba(54, 162, 235, ${alpha})`,
            `rgba(255, 205, 86, ${alpha})`,
            `rgba(75, 192, 192, ${alpha})`,
            `rgba(153, 102, 255, ${alpha})`,
            `rgba(255, 159, 64, ${alpha})`,
            `rgba(199, 199, 199, ${alpha})`,
            `rgba(83, 102, 255, ${alpha})`,
            `rgba(255, 99, 255, ${alpha})`,
            `rgba(99, 255, 132, ${alpha})`
        ];
        
        // 如果需要更多颜色，生成随机颜色
        while (colors.length < count) {
            const r = Math.floor(Math.random() * 255);
            const g = Math.floor(Math.random() * 255);
            const b = Math.floor(Math.random() * 255);
            colors.push(`rgba(${r}, ${g}, ${b}, ${alpha})`);
        }
        
        return colors.slice(0, count);
    }
}

// 全局函数
function toggleTheme() {
    const currentTheme = dashboard.userPreferences.theme;
    const newTheme = currentTheme === 'light' ? 'dark' : 'light';
    dashboard.applyTheme(newTheme);
}

function toggleConfigPanel() {
    const panel = document.getElementById('configPanel');
    if (panel) {
        panel.classList.toggle('active');
    }
}

function resetLayout() {
    dashboard.resetLayout();
}

function saveLayout() {
    dashboard.saveLayout();
    dashboard.showNotification('布局已保存');
}

function goBack() {
    if (window.history.length > 1) {
        window.history.back();
    } else {
        window.location.href = '../index.html';
    }
}

// 页面函数
function firstPage() { dashboard.firstPage(); }
function previousPage() { dashboard.previousPage(); }
function nextPage() { dashboard.nextPage(); }
function lastPage() { dashboard.lastPage(); }
function changePageSize(size) { dashboard.changePageSize(size); }
function applyTableFilters() { dashboard.applyTableFilters(); }
function resetTableFilters() { dashboard.resetTableFilters(); }
function searchJobs() { dashboard.searchJobs(); }
function sortTable(index) { dashboard.sortTable(index); }
function exportData() { dashboard.exportData(); }
function refreshChart(chartId) { jhDashboard.refreshChart(chartId); }
function changeChartType(chartId, type) { jhDashboard.changeChartType(chartId, type); }
function changeDimension(chartId, dimension) { jhDashboard.changeDimension(chartId, dimension); }
function applySalaryFilter() { dashboard.applySalaryFilter(); }
function resetAllFilters() { dashboard.resetAllFilters(); }
function toggleFilters() { dashboard.toggleFilters(); }
function selectFilter(filterType, value, element) { 
    if (jhDashboard) {
        jhDashboard.selectFilter(filterType, value, element); 
    }
}

// 初始化仪表板
let dashboard;
let jhDashboard; // 全局引用，供HTML中的onclick事件使用

document.addEventListener('DOMContentLoaded', () => {
    dashboard = new JHDashboard();
    jhDashboard = dashboard; // 创建全局引用
    
    // 默认激活第一个标签页
    setTimeout(() => {
        initializeTabContent('visualization');
    }, 100); // 稍微延迟以确保仪表板初始化完成
});

// 添加通知动画样式
const style = document.createElement('style');
style.textContent = `
    @keyframes slideIn {
        from {
            transform: translateX(100%);
            opacity: 0;
        }
        to {
            transform: translateX(0);
            opacity: 1;
        }
    }
    
    @keyframes slideOut {
        from {
            transform: translateX(0);
            opacity: 1;
        }
        to {
            transform: translateX(100%);
            opacity: 0;
        }
    }
    
    .skill-tag {
        display: inline-block;
        background: var(--bg-secondary);
        color: var(--text-primary);
        padding: 0.2rem 0.5rem;
        border-radius: 12px;
        font-size: 0.75rem;
        margin: 0.1rem;
        border: 1px solid var(--border-light);
    }
    
    .remote-badge {
        padding: 0.2rem 0.5rem;
        border-radius: 4px;
        font-size: 0.75rem;
        font-weight: 500;
    }
    
    .remote-yes {
        background: #10b981;
        color: white;
    }
    
    .remote-no {
        background: var(--border-light);
        color: var(--text-secondary);
    }
`;
document.head.appendChild(style);

// ===========================================
// 主标签页切换功能
// ===========================================

// 全局变量保存当前活跃的标签页
let currentActiveTab = 'visualization';

/**
 * 切换主标签页
 * @param {string} tabId 标签页ID
 * @param {HTMLElement} buttonElement 按钮元素
 */
function switchMainTab(tabId, buttonElement) {
    // 移除所有标签页的活跃状态
    document.querySelectorAll('.main-tab').forEach(tab => {
        tab.classList.remove('active');
    });
    
    document.querySelectorAll('.tab-content').forEach(content => {
        content.classList.remove('active');
    });
    
    // 激活选中的标签页
    buttonElement.classList.add('active');
    const targetContent = document.getElementById(tabId + '-tab');
    if (targetContent) {
        targetContent.classList.add('active');
    }
    
    currentActiveTab = tabId;
    
    // 根据标签页执行特定的初始化逻辑
    initializeTabContent(tabId);
}

/**
 * 初始化标签页内容
 * @param {string} tabId 标签页ID
 */
function initializeTabContent(tabId) {
    switch (tabId) {
        case 'visualization':
            // 数据可视化标签页已经在初始化时加载
            break;
        case 'self-analysis':
            initializeSelfAnalysis();
            break;
        case 'smart-matching':
            initializeSmartMatching();
            break;
        case 'interview-strategy':
            initializeInterviewStrategy();
            break;
        case 'ai-assistant':
            initializeAIAssistant();
            break;
    }
}

// ===========================================
// 自身分析功能
// ===========================================

let userSkills = []; // 存储用户技能

function initializeSelfAnalysis() {
    console.log('初始化自身分析模块...');
    
    // 初始化文件上传功能
    const resumeFile = document.getElementById('resumeFile');
    if (resumeFile) {
        resumeFile.addEventListener('change', handleResumeUpload);
    }
    
    // 初始化拖拽上传
    const uploadArea = document.getElementById('resumeUpload');
    if (uploadArea) {
        uploadArea.addEventListener('dragover', handleDragOver);
        uploadArea.addEventListener('drop', handleFileDrop);
        uploadArea.addEventListener('dragleave', handleDragLeave);
        // 新增：点击整个上传区域触发文件选择
        uploadArea.addEventListener('click', () => {
            const fileInput = document.getElementById('resumeFile');
            if (fileInput) fileInput.click();
        });
    }
    
    // 初始化手动填写表单
    initializeManualForm();
}

// 分析方式切换
function switchAnalysisMethod(method, buttonElement) {
    // 移除所有活跃状态
    document.querySelectorAll('.method-tab').forEach(tab => {
        tab.classList.remove('active');
    });
    document.querySelectorAll('.analysis-method-content').forEach(content => {
        content.classList.remove('active');
        // 确保隐藏所有方式面板
        content.style.display = 'none';
    });
    
    // 激活选中的方式
    buttonElement.classList.add('active');
    const target = document.getElementById(method + '-method');
    if (target) {
        target.classList.add('active');
        // 显示当前方式面板
        target.style.display = 'block';
    }

    // 确保方式选择器可见（可能之前被结果视图隐藏）
    const selector = document.querySelector('.analysis-method-selector');
    if (selector) {
        selector.style.display = 'block';
    }
    
    // 隐藏分析结果
    document.getElementById('analysisResults').style.display = 'none';
}

// 初始化手动填写表单
function initializeManualForm() {
    const skillInput = document.getElementById('skillInput');
    const manualForm = document.getElementById('manualResumeForm');
    
    if (skillInput) {
        skillInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                addSkillTag();
            }
        });
    }
    
    if (manualForm) {
        manualForm.addEventListener('submit', handleManualFormSubmit);
    }
}

// 添加技能标签
function addSkillTag() {
    const skillInput = document.getElementById('skillInput');
    const skillsTags = document.getElementById('skillsTags');
    const skill = skillInput.value.trim();
    
    if (skill && !userSkills.includes(skill)) {
        userSkills.push(skill);
        
        const tag = document.createElement('span');
        tag.className = 'skill-tag';
        tag.innerHTML = `
            ${skill}
            <i class="fas fa-times" onclick="removeSkillTag('${skill}', this)"></i>
        `;
        
        skillsTags.appendChild(tag);
        skillInput.value = '';
    }
}

// 移除技能标签
function removeSkillTag(skill, element) {
    userSkills = userSkills.filter(s => s !== skill);
    element.parentElement.remove();
}

// 清空手动表单
function clearManualForm() {
    document.getElementById('manualResumeForm').reset();
    userSkills = [];
    document.getElementById('skillsTags').innerHTML = '';
}

// 处理手动表单提交
async function handleManualFormSubmit(e) {
    e.preventDefault();
    
    const formData = new FormData(e.target);
    const resumeData = {
        name: formData.get('name'),
        email: formData.get('email'),
        phone: formData.get('phone'),
        education: formData.get('education'),
        experience: formData.get('experience'),
        skills: userSkills,
        summary: formData.get('summary'),
        target_position: formData.get('target_position'),
        expected_salary: formData.get('expected_salary')
    };
    
    try {
        await analyzeManualResume(resumeData);
    } catch (error) {
        console.error('分析失败:', error);
        alert('分析失败，请稍后重试');
    }
}

// 拖拽事件处理
function handleDragOver(e) {
    e.preventDefault();
    e.currentTarget.style.borderColor = '#667eea';
    e.currentTarget.style.background = 'rgba(102, 126, 234, 0.05)';
}

function handleDragLeave(e) {
    e.currentTarget.style.borderColor = '';
    e.currentTarget.style.background = '';
}

function handleFileDrop(e) {
    e.preventDefault();
    const files = e.dataTransfer.files;
    if (files.length > 0) {
        processResumeFile(files[0]);
    }
    
    // 重置样式
    e.currentTarget.style.borderColor = '';
    e.currentTarget.style.background = '';
}

function handleResumeUpload(e) {
    const file = e.target.files[0];
    if (file) {
        processResumeFile(file);
    }
}

// 处理文件上传和分析
async function processResumeFile(file) {
    console.log('处理简历文件:', file.name);
    
    // 检查文件大小（10MB限制）
    if (file.size > 10 * 1024 * 1024) {
        alert('文件大小不能超过10MB');
        return;
    }
    
    // 显示上传进度
    showUploadProgress();
    
    try {
        const formData = new FormData();
        formData.append('file', file);
        
        const response = await fetch('/api/jh/resume/upload', {
            method: 'POST',
            body: formData
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const result = await response.json();
        console.log('文件上传成功:', result);
        
        // 显示分析结果
        displayAnalysisResults(result.analysis);
        
    } catch (error) {
        console.error('文件上传失败:', error);
        resetUploadArea();
        alert('文件上传失败，请稍后重试');
    }
}

// 分析手动输入的简历
async function analyzeManualResume(resumeData) {
    try {
        const response = await fetch('/api/jh/resume/manual', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(resumeData)
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const result = await response.json();
        console.log('手动分析成功:', result);
        
        // 显示分析结果
        displayAnalysisResults(result.analysis);
        
    } catch (error) {
        console.error('手动分析失败:', error);
        throw error;
    }
}

// 显示上传进度
function showUploadProgress() {
    const uploadArea = document.getElementById('resumeUpload');
    const progressDiv = document.getElementById('uploadProgress');
    
    uploadArea.style.display = 'none';
    progressDiv.style.display = 'block';
    
    // 模拟进度
    let progress = 0;
    const interval = setInterval(() => {
        progress += Math.random() * 30;
        if (progress > 100) progress = 100;
        
        document.getElementById('uploadProgressBar').style.width = progress + '%';
        document.getElementById('uploadProgressText').textContent = `上传中... ${Math.round(progress)}%`;
        
        if (progress >= 100) {
            clearInterval(interval);
            document.getElementById('uploadProgressText').textContent = '分析中...';
        }
    }, 200);
}

// 重置上传区域
function resetUploadArea() {
    const progressDiv = document.getElementById('uploadProgress');
    const uploadArea = document.getElementById('resumeUpload');
    if (progressDiv) progressDiv.style.display = 'none';
    if (uploadArea) {
        // 恢复为样式表定义的显示方式（flex），避免按钮错位
        uploadArea.style.display = '';
        // 清理拖拽时设置的临时样式
        uploadArea.style.borderColor = '';
        uploadArea.style.background = '';
    }
}

// 显示分析结果
function displayAnalysisResults(analysisData) {
    // 隐藏方法选择区域，显示结果区域
    document.querySelector('.analysis-method-selector').style.display = 'none';
    document.querySelectorAll('.analysis-method-content').forEach(content => {
        content.style.display = 'none';
    });
    document.getElementById('analysisResults').style.display = 'block';
    
    // 缓存最近一次分析数据供推荐/对比等功能使用
    window.lastAnalysisData = analysisData;
    
    // 显示技能分析结果
    displaySkillAnalysis(analysisData.skill_matches);

    // 新增：匹配度分解图与强弱项小雷达
    renderMatchBreakdownChart(analysisData);
    // 渲染能力雷达图（如果数据可用）
    renderCapabilityRadarChart(analysisData);
    
    // 更新竞争力指标
    updateCompetitivenessMetrics(analysisData);
    
    // 显示推荐职位
    displayRecommendedPositions(analysisData.recommended_positions);
    
    // 显示技能建议
    displaySkillSuggestions(analysisData.missing_skills, analysisData.strength_areas);
    
    // 显示职业发展建议
    displayCareerSuggestions(analysisData.career_suggestions);
}

let capabilityRadarChartInstance = null;

function renderCapabilityRadarChart(analysisData) {
    const canvas = document.getElementById('capabilityRadarChart');
    if (!canvas) return;

    // 推断或准备雷达维度数据
    // 优先使用后端提供的字段；否则从已有指标推断
    const dimensions = [];
    const values = [];

    // 1) 如果有后端整体字段
    if (analysisData.capability_dimensions && Array.isArray(analysisData.capability_dimensions)) {
        analysisData.capability_dimensions.forEach(dim => {
            if (dim && typeof dim.name === 'string' && typeof dim.score === 'number') {
                dimensions.push(dim.name);
                values.push(dim.score);
            }
        });
    }

    // 2) 兜底：根据已有数据构造更丰富的能力维度，避免与下方表格重复
    if (dimensions.length === 0) {
        const norm = (v) => {
            if (v == null || isNaN(v)) return 0;
            if (v > 0 && v <= 1) return Math.round(v * 1000) / 10;
            return Math.max(0, Math.min(100, Math.round(v * 10) / 10));
        };

        // 衍生维度：从技能分布推断
        const skillValues = Object.values(analysisData.skill_matches || {});
        const avgSkill = skillValues.length ? (skillValues.reduce((a,b)=>a+b,0) / skillValues.length) : 0;
        const consistency = skillValues.length ? (100 - (Math.min(100, (Math.max(...skillValues) - Math.min(...skillValues))))) : 50;

        const skillsCount = Object.keys(analysisData.skill_matches || {}).length;
        const breadth = Math.min(100, skillsCount * 10); // 粗略以已匹配技能数量体现广度

        const sorted = [...skillValues].sort((a,b)=>b-a);
        const top3Avg = sorted.length ? (sorted.slice(0,3).reduce((a,b)=>a+b,0) / Math.min(3, sorted.length)) : 0;
        const bottom3Avg = sorted.length ? (sorted.slice(-3).reduce((a,b)=>a+b,0) / Math.min(3, sorted.length)) : 0;
        const strengthCount = Array.isArray(analysisData.strength_areas) ? analysisData.strength_areas.length : 0;
        const missingCount = Array.isArray(analysisData.missing_skills) ? analysisData.missing_skills.length : 0;
        const readiness = Math.max(0, Math.min(100, 70 + (strengthCount - missingCount) * 5));
        const growthPotential = (avgSkill + consistency) / 2;

        const guessed = [
            { name: '专业技能', value: norm(avgSkill) },
            { name: '核心优势', value: norm(top3Avg) },
            { name: '基础能力', value: norm(bottom3Avg) },
            { name: '技能均衡度', value: norm(consistency) },
            { name: '技能广度', value: norm(breadth) },
            { name: '成长潜力', value: norm(growthPotential) },
            { name: '求职准备度', value: norm(readiness) }
        ];
        guessed.forEach(g => { dimensions.push(g.name); values.push(g.value); });
    }

    if (capabilityRadarChartInstance) {
        capabilityRadarChartInstance.destroy();
        capabilityRadarChartInstance = null;
    }

    const ctx = canvas.getContext('2d');
    capabilityRadarChartInstance = new Chart(ctx, {
        type: 'radar',
        data: {
            labels: dimensions,
            datasets: [{
                label: '综合能力雷达',
                data: values,
                backgroundColor: 'rgba(102, 126, 234, 0.2)',
                borderColor: 'rgba(102, 126, 234, 1)',
                pointBackgroundColor: 'rgba(102, 126, 234, 1)',
                pointBorderColor: '#fff',
                pointHoverBackgroundColor: '#fff',
                pointHoverBorderColor: 'rgba(102, 126, 234, 1)'
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
                r: {
                    suggestedMin: 0,
                    suggestedMax: 100,
                    ticks: { stepSize: 20 },
                    grid: { color: 'rgba(0,0,0,0.1)' },
                    angleLines: { color: 'rgba(0,0,0,0.1)' },
                    pointLabels: { color: 'var(--text-primary)' }
                }
            },
            plugins: {
                legend: { display: false },
                tooltip: { enabled: true },
                title: {
                    display: true,
                    text: '七维综合能力（0-100）',
                    color: 'var(--text-secondary)',
                    font: { size: 12 }
                }
            }
        }
    });
}

// 显示技能分析结果
function displaySkillAnalysis(skillMatches) {
    const container = document.getElementById('skillAnalysisResults');
    
    if (!skillMatches || Object.keys(skillMatches).length === 0) {
        container.innerHTML = '<p class="no-data">未检测到相关技能信息</p>';
        return;
    }
    
    let html = '<h4>技能匹配度</h4>';
    
    // 按分数排序
    const sortedSkills = Object.entries(skillMatches).sort((a, b) => b[1] - a[1]);
    
    sortedSkills.forEach(([skill, score]) => {
        const level = score >= 80 ? 'excellent' : score >= 60 ? 'good' : 'average';
        const percent = Math.max(0, Math.min(100, Number.isFinite(score) ? score : 0));
        html += `
            <div class="skill-match-item">
                <div class="skill-info">
                    <span class="skill-name">${skill}</span>
                    <span class="skill-score ${level}">${percent.toFixed(1)}%</span>
                </div>
                <div class="skill-match-bar">
                    <div class="skill-match-progress ${level}" style="width: ${percent}%"></div>
                </div>
            </div>
        `;
    });
    
    container.innerHTML = html;
}

// 更新竞争力指标
function updateCompetitivenessMetrics(analysisData) {
    const normalizePercent = (v) => {
        if (v == null || isNaN(v)) return 0;
        // 若已是 0-1 之间的小数，转百分比
        if (v > 0 && v <= 1) return Math.round(v * 1000) / 10;
        // 否则按 0-100 裁剪
        return Math.max(0, Math.min(100, Math.round(v * 10) / 10));
    };

    const metrics = [
        { id: 'overallCompetitiveness', scoreId: 'overallScore', value: normalizePercent(analysisData.competitiveness_score), suffix: '分' },
        { id: 'skillMatchProgress', scoreId: 'skillMatchScore', value: normalizePercent(analysisData.skill_match_score), suffix: '%' },
        { id: 'salaryCompetitiveness', scoreId: 'salaryScore', value: normalizePercent(analysisData.salary_competitiveness), suffix: '分' }
    ];
    
    metrics.forEach((metric, index) => {
        setTimeout(() => {
            const progressElement = document.getElementById(metric.id);
            const scoreElement = document.getElementById(metric.scoreId);
            
            if (progressElement && scoreElement) {
                progressElement.style.width = metric.value + '%';
                scoreElement.textContent = metric.value.toFixed(1) + metric.suffix;
            }
        }, index * 300);
    });
}

// 显示推荐职位
function displayRecommendedPositions(positions) {
    const container = document.getElementById('recommendedPositions');
    
    if (!positions || positions.length === 0) {
        container.innerHTML = '<p class="no-data">暂无推荐职位</p>';
        return;
    }
    
    const sanitize = (v) => (v == null ? '' : String(v));
    const sorted = positions.slice().sort((a,b)=> (Number(b.match_score)||0) - (Number(a.match_score)||0));
    let html = '<div class="job-list">';
    sorted.forEach(position => {
        const tags = Array.isArray(position.tags) ? position.tags : (position.skills || '').split(',').slice(0,6);
        const jobId = sanitize(position.id || position.job_id || position.url || (position.title + '|' + position.company + '|' + position.location));
        const match = Math.max(0, Math.min(100, Number(position.match_score)||0));
        html += `
            <div class="job-item job-card" data-id="${jobId}">
                <div class="job-item-main">
                    <div class="job-item-title">
                        <h4>${sanitize(position.title)}</h4>
                        <span class="job-badge">${sanitize(position.type || '全职')}</span>
                    </div>
                    <div class="job-item-company">
                        <span class="company-name">${sanitize(position.company)}</span>
                        <span class="separator">·</span>
                        <span class="job-location"><i class="fas fa-map-marker-alt"></i>${sanitize(position.location)}</span>
                        <span class="separator">·</span>
                        <span class="job-salary"><i class="fas fa-yen-sign"></i>${sanitize(position.salary_range)}</span>
                    </div>
                    <div class="job-item-tags">
                        ${tags.filter(Boolean).map(t => `<span class="job-tag">${sanitize(t).trim()}</span>`).join('')}
                    </div>
                </div>
                <div class="job-item-side">
                    <span class="job-match-pill">${match}%</span>
                    <div class="job-item-actions">
                        <button class="btn btn-outline btn-sm" data-action="compare" data-id="${jobId}">对比</button>
                        <button class="btn btn-secondary btn-sm" data-action="favorite" data-id="${jobId}">收藏</button>
                        <button class="btn btn-primary btn-sm" data-action="detail" data-id="${jobId}">查看详情</button>
                    </div>
                </div>
            </div>
        `;
    });
    html += '</div>';
    
    container.innerHTML = html;

    ensureRecommendedMeta(container);
    attachRecommendedPositionHandlers(container, sorted);

    // 启用推荐职位增强（分页与补充推荐）
    setupRecommendedPositionsEnhancements(container, sorted);
}

// 小型：匹配度分解图（柱状）
function renderMatchBreakdownChart(analysisData) {
    const container = document.getElementById('matchBreakdown');
    if (!container) return;
    const canvas = container.querySelector('canvas') || (()=>{ const c=document.createElement('canvas'); container.appendChild(c); return c; })();
    const ctx = canvas.getContext('2d');

    const norm = (v)=>{
        if (v == null || isNaN(v)) return 0;
        if (v > 0 && v <= 1) return Math.round(v*1000)/10;
        return Math.max(0, Math.min(100, Math.round(v*10)/10));
    };

    const skillValues = Object.values(analysisData.skill_matches || {});
    const avgSkill = skillValues.length ? (skillValues.reduce((a,b)=>a+b,0)/skillValues.length) : 0;
    const experienceScore = norm(analysisData.competitiveness_score);
    const salaryScore = norm(analysisData.salary_competitiveness);

    const completeness = (()=>{
        const total = Object.keys(analysisData.skill_matches || {}).length;
        const missing = Array.isArray(analysisData.missing_skills) ? analysisData.missing_skills.length : 0;
        if (total + missing === 0) return 0;
        return Math.round((total / (total + missing)) * 1000) / 10;
    })();
    const readiness = (()=>{
        const strengths = Array.isArray(analysisData.strength_areas) ? analysisData.strength_areas.length : 0;
        const missing = Array.isArray(analysisData.missing_skills) ? analysisData.missing_skills.length : 0;
        return Math.max(0, Math.min(100, 70 + (strengths - missing) * 5));
    })();

    const labels = ['技能', '经验/教育', '薪资匹配', '技能完整度', '求职准备度'];
    const data = [norm(avgSkill), experienceScore, salaryScore, completeness, readiness];

    if (window.matchBreakdownChart) {
        window.matchBreakdownChart.destroy();
    }
    window.matchBreakdownChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels,
            datasets: [{
                label: '分项得分',
                data,
                backgroundColor: ['#667eea55','#22c55e55','#f59e0b55','#06b6d455','#ef444455'],
                borderColor: ['#667eea','#22c55e','#f59e0b','#06b6d4','#ef4444'],
                borderWidth: 1
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
                y: { beginAtZero: true, max: 100 }
            },
            plugins: {
                legend: { display: false },
                tooltip: {
                    callbacks: {
                        label: (ctx) => `${ctx.label}: ${ctx.formattedValue} 分`
                    }
                },
                title: {
                    display: true,
                    text: '匹配度分解（0-100）',
                    color: 'var(--text-secondary)',
                    font: { size: 12 }
                }
            }
        }
    });
}

// 小型：强弱项小雷达
function renderStrengthWeaknessMiniRadar_REMOVED(analysisData) {
    const container = document.getElementById('miniRadar');
    if (!container) return;
    const canvas = container.querySelector('canvas') || (()=>{ const c=document.createElement('canvas'); container.appendChild(c); return c; })();
    const ctx = canvas.getContext('2d');

    const skills = Object.entries(analysisData.skill_matches || {});
    if (skills.length === 0) { container.innerHTML = '<p class="no-data">暂无数据</p>'; return; }
    const sorted = skills.sort((a,b)=>b[1]-a[1]);
    const top = sorted.slice(0,3);
    const bottom = sorted.slice(-3);
    const dims = [...top.map(([k])=>`强:${k}`), ...bottom.map(([k])=>`弱:${k}`)];
    const vals = [...top.map(([,v])=>Math.max(0,Math.min(100,v))), ...bottom.map(([,v])=>Math.max(0,Math.min(100,v)))];

    if (window.miniRadarChart) {
        window.miniRadarChart.destroy();
    }
    window.miniRadarChart = new Chart(ctx, {
        type: 'radar',
        data: {
            labels: dims,
            datasets: [{
                label: '强弱项对比',
                data: vals,
                backgroundColor: 'rgba(34,197,94,0.15)',
                borderColor: 'rgba(34,197,94,0.9)',
                pointBackgroundColor: 'rgba(34,197,94,0.9)'
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: { legend: { display: false } },
            scales: { r: { suggestedMin: 0, suggestedMax: 100 } }
        }
    });
}

// 显示技能建议
function displaySkillSuggestions(missingSkills, strengthAreas) {
    const container = document.getElementById('skillSuggestions');
    
    let html = '';
    
    if (strengthAreas && strengthAreas.length > 0) {
        html += `
            <div class="suggestion-section">
                <h4><i class="fas fa-star"></i> 您的优势领域</h4>
                <div class="strength-tags">
                    ${strengthAreas.map(area => `<span class="strength-tag">${area}</span>`).join('')}
                </div>
            </div>
        `;
    }
    
    if (missingSkills && missingSkills.length > 0) {
        html += `
            <div class="suggestion-section">
                <h4><i class="fas fa-exclamation-triangle"></i> 建议补强技能</h4>
                <div class="missing-skills">
                    ${missingSkills.map(skill => `<span class="missing-skill-tag">${skill}</span>`).join('')}
                </div>
            </div>
        `;
    }
    
    container.innerHTML = html || '<p class="no-data">暂无技能建议</p>';
}

// 显示职业发展建议
function displayCareerSuggestions(suggestions) {
    const container = document.getElementById('careerSuggestions');
    
    if (!suggestions || suggestions.length === 0) {
        container.innerHTML = '<p class="no-data">暂无职业发展建议</p>';
        return;
    }
    
    let html = '';
    suggestions.forEach((suggestion, index) => {
        const icons = ['fas fa-lightbulb', 'fas fa-chart-line', 'fas fa-target', 'fas fa-rocket', 'fas fa-graduation-cap'];
        const icon = icons[index % icons.length];
        
        html += `
            <div class="career-suggestion-item">
                <div class="suggestion-icon">
                    <i class="${icon}"></i>
                </div>
                <div class="suggestion-content">
                    <p>${suggestion}</p>
                </div>
            </div>
        `;
    });
    
    container.innerHTML = html;
}

// 重置分析
function resetAnalysis() {
    // 显示方法选择区域
    const selector = document.querySelector('.analysis-method-selector');
    if (selector) selector.style.display = 'block';

    // 清理方法tab激活态
    document.querySelectorAll('.method-tab').forEach(tab => tab.classList.remove('active'));
    document.querySelector('.method-tab[data-method="upload"]').classList.add('active');

    // 隐藏并移除所有方式面板的active，再显示默认上传方式
    document.querySelectorAll('.analysis-method-content').forEach(content => {
        content.classList.remove('active');
        content.style.display = 'none';
    });
    const upload = document.getElementById('upload-method');
    if (upload) {
        upload.classList.add('active');
        upload.style.display = 'block';
    }
    
    // 隐藏结果区域
    document.getElementById('analysisResults').style.display = 'none';

    // 销毁雷达图实例
    if (capabilityRadarChartInstance) {
        capabilityRadarChartInstance.destroy();
        capabilityRadarChartInstance = null;
    }
    
    // 重置上传区域
    resetUploadArea();
    
    // 清空表单
    clearManualForm();
}

// ===========================================
// 智能匹配功能
// ===========================================

function initializeSmartMatching() {
    console.log('初始化智能匹配模块...');
    
    const startMatchingBtn = document.getElementById('startMatching');
    if (startMatchingBtn) {
        startMatchingBtn.addEventListener('click', performSmartMatching);
    }
}

function performSmartMatching() {
    console.log('开始智能匹配...');
    
    // 获取用户偏好
    const preferences = {
        jobType: document.getElementById('preferredJobType').value,
        location: document.getElementById('preferredLocation').value,
        salaryMin: document.getElementById('expectedSalaryMin').value,
        salaryMax: document.getElementById('expectedSalaryMax').value,
        remote: document.getElementById('remotePreference').value
    };
    
    // 显示匹配结果
    const resultsContainer = document.getElementById('matchingResults');
    resultsContainer.style.display = 'block';
    
    // 模拟匹配过程
    const recommendationsContainer = document.getElementById('jobRecommendations');
    recommendationsContainer.innerHTML = `
        <div class="loading-message">
            <i class="fas fa-spinner fa-spin"></i>
            <p>正在为您匹配最适合的职位...</p>
        </div>
    `;
    
    setTimeout(() => {
        showJobRecommendations();
    }, 2000);
}

function showJobRecommendations() {
    const recommendationsContainer = document.getElementById('jobRecommendations');
    recommendationsContainer.innerHTML = `
        <div class="job-recommendation-card">
            <div class="job-rec-header">
                <h4>Senior Data Scientist</h4>
                <span class="match-score">匹配度: 92%</span>
            </div>
            <div class="job-rec-company">Google</div>
            <div class="job-rec-location">Mountain View, CA (Remote Friendly)</div>
            <div class="job-rec-salary">$140K - $180K</div>
            <div class="job-rec-skills">Python, TensorFlow, Machine Learning, Statistics</div>
            <button class="btn btn-primary btn-sm">查看详情</button>
        </div>
        
        <div class="job-recommendation-card">
            <div class="job-rec-header">
                <h4>Machine Learning Engineer</h4>
                <span class="match-score">匹配度: 88%</span>
            </div>
            <div class="job-rec-company">Microsoft</div>
            <div class="job-rec-location">Seattle, WA</div>
            <div class="job-rec-salary">$130K - $170K</div>
            <div class="job-rec-skills">PyTorch, Kubernetes, MLOps, Python</div>
            <button class="btn btn-primary btn-sm">查看详情</button>
        </div>
        
        <div class="job-recommendation-card">
            <div class="job-rec-header">
                <h4>Data Engineer</h4>
                <span class="match-score">匹配度: 85%</span>
            </div>
            <div class="job-rec-company">Amazon</div>
            <div class="job-rec-location">Austin, TX</div>
            <div class="job-rec-salary">$120K - $160K</div>
            <div class="job-rec-skills">AWS, Spark, SQL, Python, Kafka</div>
            <button class="btn btn-primary btn-sm">查看详情</button>
        </div>
    `;
}

// ===========================================
// 面试策略功能
// ===========================================

function initializeInterviewStrategy() {
    console.log('初始化面试策略模块...');
    
    const generateBtn = document.getElementById('generateStrategy');
    if (generateBtn) {
        generateBtn.addEventListener('click', generateInterviewStrategy);
    }
}

function generateInterviewStrategy() {
    const position = document.getElementById('targetPosition').value;
    const stage = document.getElementById('interviewStage').value;
    
    if (!position) {
        alert('请选择目标职位');
        return;
    }
    
    console.log('生成面试策略:', position, stage);
    
    const outputContainer = document.getElementById('strategyOutput');
    outputContainer.style.display = 'block';
    
    // 生成策略内容
    generateStrategyContent(position, stage);
    
    // 初始化策略标签页切换
    initializeStrategyTabs();
}

function generateStrategyContent(position, stage) {
    const questionsContent = document.getElementById('questionsContent');
    const answersContent = document.getElementById('answersContent');
    const tipsContent = document.getElementById('tipsContent');
    
    // 根据职位和阶段生成内容
    const strategies = getInterviewStrategies(position, stage);
    
    questionsContent.innerHTML = strategies.questions;
    answersContent.innerHTML = strategies.answers;
    tipsContent.innerHTML = strategies.tips;
}

function getInterviewStrategies(position, stage) {
    // 这里可以根据不同的职位和阶段返回不同的策略内容
    return {
        questions: `
            <div class="strategy-list">
                <h4>常见面试问题</h4>
                <ul>
                    <li>请介绍一下您的工作经验和技能背景</li>
                    <li>为什么选择${position}这个职位？</li>
                    <li>描述一个您解决复杂技术问题的例子</li>
                    <li>您如何保持技术技能的更新？</li>
                    <li>在团队合作中，您通常扮演什么角色？</li>
                </ul>
            </div>
        `,
        answers: `
            <div class="strategy-list">
                <h4>参考答案思路</h4>
                <div class="answer-item">
                    <h5>自我介绍要点：</h5>
                    <p>• 突出与职位相关的核心技能<br>
                    • 提及具体的项目经验和成果<br>
                    • 展示学习能力和适应性</p>
                </div>
                <div class="answer-item">
                    <h5>技术问题回答策略：</h5>
                    <p>• 使用STAR方法（情况-任务-行动-结果）<br>
                    • 详细描述解决问题的思路和过程<br>
                    • 强调从中学到的经验和教训</p>
                </div>
            </div>
        `,
        tips: `
            <div class="strategy-list">
                <h4>面试技巧</h4>
                <div class="tip-item">
                    <h5><i class="fas fa-clock"></i> 时间管理</h5>
                    <p>提前15分钟到达，准备充分但不要过度紧张</p>
                </div>
                <div class="tip-item">
                    <h5><i class="fas fa-comments"></i> 沟通技巧</h5>
                    <p>保持眼神接触，语速适中，思考后再回答</p>
                </div>
                <div class="tip-item">
                    <h5><i class="fas fa-question"></i> 提问环节</h5>
                    <p>准备3-5个有质量的问题，展示对公司和职位的兴趣</p>
                </div>
            </div>
        `
    };
}

function initializeStrategyTabs() {
    const strategyTabs = document.querySelectorAll('.strategy-tab');
    strategyTabs.forEach(tab => {
        tab.addEventListener('click', function() {
            // 移除所有活跃状态
            strategyTabs.forEach(t => t.classList.remove('active'));
            document.querySelectorAll('.strategy-tab-content').forEach(content => {
                content.classList.remove('active');
            });
            
            // 激活选中的标签页
            this.classList.add('active');
            const tabName = this.getAttribute('data-tab');
            document.getElementById(tabName + 'Content').classList.add('active');
        });
    });
}

// ===========================================
// AI助手功能
// ===========================================

function initializeAIAssistant() {
    console.log('初始化AI助手模块...');
    
    // 绑定发送消息事件
    const sendButton = document.querySelector('#ai-assistant-tab .btn-primary');
    if (sendButton) {
        sendButton.addEventListener('click', sendChatMessage);
    }
    
    // 绑定回车发送
    const chatInput = document.getElementById('chatInput');
    if (chatInput) {
        chatInput.addEventListener('keypress', handleChatEnter);
    }
    
    // 检查AI服务状态
    checkAIServiceStatus();
    
    // 加载建议话题
    loadChatSuggestions();
}

async function checkAIServiceStatus() {
    try {
        const response = await fetch('http://localhost:8000/api/jh/chat/status');
        const data = await response.json();
        
        if (data.ollama_available && data.qwen_model_available) {
            console.log('AI服务状态正常');
            updateAIServiceStatusUI(true, `当前模型: ${data.current_model}`);
        } else {
            console.warn('AI服务不可用');
            updateAIServiceStatusUI(false, data.error || 'AI服务暂时不可用');
        }
    } catch (error) {
        console.error('检查AI服务状态失败:', error);
        updateAIServiceStatusUI(false, '无法连接到AI服务');
    }
}

function updateAIServiceStatusUI(isAvailable, message) {
    const chatContainer = document.querySelector('.chat-interface');
    if (!chatContainer) return;
    
    // 移除现有的状态提示
    const existingStatus = chatContainer.querySelector('.ai-status-banner');
    if (existingStatus) existingStatus.remove();
    
    if (!isAvailable) {
        const statusBanner = document.createElement('div');
        statusBanner.className = 'ai-status-banner warning';
        statusBanner.innerHTML = `
            <i class="fas fa-exclamation-triangle"></i>
            <span>${message}</span>
        `;
        chatContainer.insertBefore(statusBanner, chatContainer.firstChild);
        
        // 禁用输入
        const chatInput = document.getElementById('chatInput');
        const sendButton = document.querySelector('#ai-assistant-tab .btn-primary');
        if (chatInput) chatInput.disabled = true;
        if (sendButton) sendButton.disabled = true;
    } else {
        // 显示成功状态
        const statusBanner = document.createElement('div');
        statusBanner.className = 'ai-status-banner success';
        statusBanner.innerHTML = `
            <i class="fas fa-check-circle"></i>
            <span>${message}</span>
        `;
        chatContainer.insertBefore(statusBanner, chatContainer.firstChild);
        
        // 3秒后自动隐藏
        setTimeout(() => {
            if (statusBanner.parentNode) {
                statusBanner.remove();
            }
        }, 3000);
    }
}

async function loadChatSuggestions() {
    try {
        const response = await fetch('http://localhost:8000/api/jh/chat/suggestions');
        const data = await response.json();
        
        if (data.suggestions) {
            displayChatSuggestions(data.suggestions);
        }
    } catch (error) {
        console.error('加载聊天建议失败:', error);
    }
}

function displayChatSuggestions(suggestions) {
    const quickQuestionsContainer = document.querySelector('.quick-questions');
    if (!quickQuestionsContainer) return;
    
    // 清空现有建议
    quickQuestionsContainer.innerHTML = '';
    
    // 随机选择几个建议显示
    const randomSuggestions = [];
    suggestions.forEach(category => {
        const randomQuestion = category.questions[Math.floor(Math.random() * category.questions.length)];
        randomSuggestions.push(randomQuestion);
    });
    
    // 显示前3个随机建议
    randomSuggestions.slice(0, 3).forEach(question => {
        const button = document.createElement('button');
        button.className = 'quick-question';
        button.textContent = question;
        button.onclick = () => sendQuickQuestion(question);
        quickQuestionsContainer.appendChild(button);
    });
}

function handleChatEnter(event) {
    if (event.key === 'Enter') {
        sendChatMessage();
    }
}

// AI聊天相关全局函数
function handleAIChatEnter(event) {
    if (event.key === 'Enter') {
        sendAIChatMessage();
    }
}

function sendAIChatMessage() {
    const input = document.getElementById('aiChatInput');
    const message = input.value.trim();
    
    if (!message) return;
    
    // 添加用户消息
    addAIChatMessage(message, 'user');
    
    // 清空输入框并禁用
    input.value = '';
    input.disabled = true;
    const sendButton = document.querySelector('.ai-chat-send');
    if (sendButton) sendButton.disabled = true;
    
    // 显示加载状态
    updateAIChatStatus('connecting', '正在分析中...');
    const loadingMessage = addAIChatLoadingMessage();
    
    // 发送到AI服务
    sendToAIService(message, loadingMessage, input, sendButton);
}

function addAIChatMessage(content, type) {
    const messagesContainer = document.getElementById('aiChatMessages');
    
    // 隐藏欢迎消息
    const welcomeMsg = messagesContainer.querySelector('.ai-chat-welcome');
    if (welcomeMsg) {
        welcomeMsg.style.display = 'none';
    }
    
    const messageDiv = document.createElement('div');
    messageDiv.className = `ai-chat-message ${type}`;
    
    const time = new Date().toLocaleTimeString('zh-CN', { 
        hour: '2-digit', 
        minute: '2-digit' 
    });
    
    messageDiv.innerHTML = `
        <div class="ai-message-content">${content}</div>
        <div class="ai-message-time">${time}</div>
    `;
    
    messagesContainer.appendChild(messageDiv);
    
    // 滚动到底部
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
    
    return messageDiv;
}

function addAIChatLoadingMessage() {
    const messagesContainer = document.getElementById('aiChatMessages');
    
    const loadingDiv = document.createElement('div');
    loadingDiv.className = 'ai-chat-message ai loading';
    
    loadingDiv.innerHTML = `
        <div class="ai-message-loading">
            <i class="fas fa-robot"></i>
            <span>正在分析图表数据</span>
            <div class="ai-loading-dots">
                <span></span>
                <span></span>
                <span></span>
            </div>
        </div>
    `;
    
    messagesContainer.appendChild(loadingDiv);
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
    
    return loadingDiv;
}

function updateAIChatStatus(status, text) {
    const indicator = document.querySelector('.ai-status-indicator');
    const statusText = document.querySelector('.ai-status-text');
    
    if (indicator) {
        indicator.className = `fas fa-circle ai-status-indicator ${status}`;
    }
    
    if (statusText) {
        statusText.textContent = text;
    }
}

async function sendToAIService(message, loadingMessage, input, sendButton) {
    try {
        // 获取当前图表数据作为上下文
        const chartContext = await gatherChartContextData();
        
        const response = await fetch('http://localhost:8000/api/jh/chat/message', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                message: message,
                context_data: chartContext,
                stream: false,
                chart_id: window.jhDashboard?.currentModalChartId || 'default'
            })
        });
        
        if (!response.ok) {
            throw new Error(`API请求失败: ${response.status}`);
        }
        
        const data = await response.json();
        
        // 移除加载消息
        if (loadingMessage) loadingMessage.remove();
        
        // 添加AI回复
        addAIChatMessage(data.response, 'ai');
        
        // 更新状态
        updateAIChatStatus('', 'AI助手已就绪');
        
    } catch (error) {
        console.error('AI聊天失败:', error);
        
        // 移除加载消息
        if (loadingMessage) loadingMessage.remove();
        
        // 显示错误消息
        addAIChatMessage('抱歉，我暂时无法分析这个图表。请检查网络连接或稍后再试。', 'ai');
        
        // 更新状态
        updateAIChatStatus('error', '连接失败');
    } finally {
        // 重新启用输入
        input.disabled = false;
        if (sendButton) sendButton.disabled = false;
        input.focus();
    }
}

async function gatherChartContextData() {
    const contextData = {
        chart_type: 'modal_chart',
        chart_id: window.jhDashboard?.currentModalChartId,
        timestamp: new Date().toISOString()
    };
    
    try {
        // 获取当前图表的配置
        const chartTypeSelect = document.getElementById('modalChartTypeSelect');
        const dimensionSelect = document.getElementById('modalDimensionSelect');
        
        if (chartTypeSelect) {
            contextData.chart_type = chartTypeSelect.value;
        }
        
        if (dimensionSelect) {
            contextData.dimension = dimensionSelect.value;
        }
        
        // 获取图表数据
        if (window.jhDashboard?.modalChart?.data) {
            const chartData = window.jhDashboard.modalChart.data;
            contextData.chart_data = {
                labels: chartData.labels,
                datasets: chartData.datasets?.map(dataset => ({
                    label: dataset.label,
                    data: dataset.data,
                    type: dataset.type
                }))
            };
            
            // 添加图表的描述性标题信息
            const chartTitle = document.querySelector('.chart-modal-header h3')?.textContent || '当前图表';
            contextData.chart_title = chartTitle;
            
            // 添加数据统计摘要
            if (chartData.datasets && chartData.datasets.length > 0) {
                const mainDataset = chartData.datasets[0];
                if (mainDataset.data) {
                    const dataArray = mainDataset.data;
                    const total = dataArray.reduce((sum, value) => sum + (typeof value === 'number' ? value : 0), 0);
                    const max = Math.max(...dataArray.filter(v => typeof v === 'number'));
                    const min = Math.min(...dataArray.filter(v => typeof v === 'number'));
                    
                    contextData.data_summary = {
                        total: total,
                        max: max,
                        min: min,
                        count: dataArray.length,
                        chart_type: contextData.chart_type,
                        dimension: contextData.dimension
                    };
                }
            }
        }
        
        // 获取当前统计数据
        const statsData = await window.jhDashboard?.getOverviewStats();
        if (statsData) {
            contextData.overview_stats = statsData;
        }
        
        // 获取当前的筛选器状态，提供更多上下文
        if (window.jhDashboard?.currentFilters) {
            contextData.current_filters = window.jhDashboard.currentFilters;
        }
        
    } catch (error) {
        console.warn('收集图表上下文数据时出错:', error);
    }
    
    return contextData;
}

// 新增：设置当前图表ID到服务端
JHDashboard.prototype.setCurrentChartOnServer = async function(chartId) {
    try {
        const response = await fetch('http://localhost:8000/api/jh/chat/conversation/chart', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                chart_id: chartId
            })
        });
        
        if (!response.ok) {
            console.warn('设置当前图表ID失败:', response.status);
        }
        
    } catch (error) {
        console.warn('设置当前图表ID时发生错误:', error);
    }
}

function selectSuggestion(element) {
    const input = document.getElementById('aiChatInput');
    if (input) {
        input.value = element.textContent;
        input.focus();
        // 可选：自动发送消息
        // sendAIChatMessage();
    }
}

async function sendChatMessage() {
    const input = document.getElementById('chatInput');
    const message = input.value.trim();
    
    if (!message) return;
    
    // 检查输入是否被禁用
    if (input.disabled) {
        addChatMessage('AI服务暂时不可用，请稍后再试。', 'ai');
        return;
    }
    
    // 添加用户消息
    addChatMessage(message, 'user');
    
    // 清空输入框并禁用
    input.value = '';
    input.disabled = true;
    const sendButton = document.querySelector('#ai-assistant-tab .btn-primary');
    if (sendButton) sendButton.disabled = true;
    
    // 显示加载状态
    const loadingMessage = addChatMessage('正在思考中...', 'ai', true);
    
    try {
        // 准备上下文数据
        const contextData = await gatherContextData();
        
        // 发送API请求
        const response = await fetch('http://localhost:8000/api/jh/chat/message', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                message: message,
                context_data: contextData,
                stream: false,
                chart_id: window.jhDashboard?.currentModalChartId || 'default'
            })
        });
        
        if (!response.ok) {
            throw new Error(`API请求失败: ${response.status}`);
        }
        
        const data = await response.json();
        
        // 移除加载消息
        if (loadingMessage) loadingMessage.remove();
        
        // 添加AI回复
        addChatMessage(data.response, 'ai');
        
    } catch (error) {
        console.error('发送消息失败:', error);
        
        // 移除加载消息
        if (loadingMessage) loadingMessage.remove();
        
        // 显示错误消息
        addChatMessage('抱歉，我暂时无法回答您的问题。请检查网络连接或稍后再试。', 'ai');
    } finally {
        // 重新启用输入
        input.disabled = false;
        if (sendButton) sendButton.disabled = false;
        input.focus();
    }
}

async function gatherContextData() {
    const contextData = {};
    
    try {
        // 获取当前可见的图表数据或统计信息
        const currentTab = document.querySelector('.main-tab.active');
        if (currentTab) {
            contextData.current_page = currentTab.dataset.tab;
        }
        
        // 如果在数据可视化标签页，获取当前图表信息
        if (contextData.current_page === 'visualization') {
            const activeChart = document.querySelector('.chart-tab.active');
            if (activeChart) {
                contextData.current_chart = activeChart.textContent.trim();
            }
        }
        
        // 获取用户输入的技能信息（如果有）
        const skillsInput = document.getElementById('skills');
        if (skillsInput && skillsInput.value) {
            contextData.user_skills = skillsInput.value.split(',').map(s => s.trim());
        }
        
        // 获取位置偏好
        const locationInput = document.getElementById('preferredLocation');
        if (locationInput && locationInput.value) {
            contextData.preferred_location = locationInput.value;
        }
        
        // 获取薪资期望
        const salaryMinInput = document.getElementById('expectedSalaryMin');
        const salaryMaxInput = document.getElementById('expectedSalaryMax');
        if (salaryMinInput && salaryMaxInput && salaryMinInput.value && salaryMaxInput.value) {
            contextData.salary_expectation = {
                min: parseInt(salaryMinInput.value),
                max: parseInt(salaryMaxInput.value)
            };
        }
        
    } catch (error) {
        console.warn('收集上下文数据时出错:', error);
    }
    
    return contextData;
}

function sendQuickQuestion(question) {
    const chatInput = document.getElementById('chatInput');
    chatInput.value = question;
    sendChatMessage();
}

function addChatMessage(message, sender, isLoading = false) {
    const messagesContainer = document.getElementById('chatMessages');
    const messageDiv = document.createElement('div');
    messageDiv.className = `message ${sender}-message ${isLoading ? 'loading' : ''}`;
    
    const avatarIcon = sender === 'ai' ? 'fas fa-robot' : 'fas fa-user';
    const timestamp = new Date().toLocaleTimeString('zh-CN', { 
        hour: '2-digit', 
        minute: '2-digit' 
    });
    
    messageDiv.innerHTML = `
        <div class="message-avatar">
            <i class="${avatarIcon}"></i>
        </div>
        <div class="message-content">
            <p>${isLoading ? '<i class="fas fa-spinner fa-spin"></i> ' + message : message}</p>
            <span class="message-time">${timestamp}</span>
        </div>
    `;
    
    messagesContainer.appendChild(messageDiv);
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
    
    return messageDiv;
}

// 添加清除对话历史的功能
async function clearChatHistory() {
    if (!confirm('确定要清除所有对话历史吗？')) {
        return;
    }
    
    try {
        const response = await fetch('/api/jh/chat/conversation/clear', {
            method: 'DELETE'
        });
        
        if (response.ok) {
            // 清除UI中的消息
            const messagesContainer = document.getElementById('chatMessages');
            const messages = messagesContainer.querySelectorAll('.message:not(.ai-message:first-child)');
            messages.forEach(msg => msg.remove());
            
            // 显示成功消息
            addChatMessage('对话历史已清除', 'ai');
        } else {
            throw new Error('清除失败');
        }
    } catch (error) {
        console.error('清除对话历史失败:', error);
        addChatMessage('清除对话历史失败，请稍后再试。', 'ai');
    }
}

function generateAIResponse(userMessage) {
    // 简单的关键词响应系统
    const responses = {
        '简历': '简历优化是求职成功的关键。建议突出与目标职位相关的技能和经验，使用具体的数字和成果来展示您的价值。您可以在自身分析模块上传简历获得详细的分析报告。',
        '面试': '面试准备需要从多个方面入手：了解公司背景、准备常见问题的答案、练习技术问题、准备提问环节。我们的面试策略模块可以为您生成个性化的面试准备方案。',
        '市场': '当前数据科学和人工智能领域就业市场整体向好，特别是机器学习、深度学习、数据工程等方向需求量大。建议关注云计算、MLOps等新兴技术方向。',
        '技能': '技能提升建议根据您的目标职位而定。对于数据科学家，重点关注Python、R、机器学习算法；对于数据工程师，重点关注大数据技术、云平台、ETL流程。',
        '薪资': '薪资水平受多个因素影响：技能水平、工作经验、地理位置、公司规模等。建议通过市场调研了解目标职位的薪资范围，在面试中合理谈判。'
    };
    
    // 查找匹配的关键词
    for (const keyword in responses) {
        if (userMessage.includes(keyword)) {
            return responses[keyword];
        }
    }
    
    // 默认回复
    return '感谢您的问题！我是您的AI求职助手，可以帮助您分析职位市场、优化简历、准备面试等。请告诉我您具体想了解什么方面的信息？';
}

// 页面加载完成后的初始化已在上面的DOMContentLoaded事件中处理

// 添加样式到页面
const newStyles = document.createElement('style');
newStyles.textContent = `
    .skill-match-item {
        display: flex;
        align-items: center;
        gap: 1rem;
        margin-bottom: 1rem;
    }
    
    .skill-match-item span:first-child {
        min-width: 80px;
        font-weight: 500;
    }
    
    .skill-match-bar {
        flex: 1;
        height: 8px;
        background: var(--border-light);
        border-radius: 4px;
        overflow: hidden;
    }
    
    .skill-match-progress {
        height: 100%;
        background: linear-gradient(90deg, #667eea, #764ba2);
        border-radius: 4px;
        transition: width 0.8s ease;
    }
    
    .career-suggestion-item {
        background: rgba(102, 126, 234, 0.05);
        border-left: 4px solid #667eea;
        padding: 1.5rem;
        margin-bottom: 1rem;
        border-radius: 6px;
    }
    
    .career-suggestion-item h4 {
        color: var(--text-primary);
        margin-bottom: 0.5rem;
        font-size: 1.1rem;
    }
    
    .career-suggestion-item h4 i {
        color: #667eea;
        margin-right: 0.5rem;
    }
    
    .job-recommendation-card {
        background: var(--bg-card);
        border: 1px solid var(--border-light);
        border-radius: 8px;
        padding: 1.5rem;
        margin-bottom: 1rem;
        transition: all 0.3s ease;
    }
    
    .job-recommendation-card:hover {
        transform: translateY(-2px);
        box-shadow: var(--shadow-hover);
    }
    
    .job-rec-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.5rem;
    }
    
    .job-rec-header h4 {
        color: var(--text-primary);
        margin: 0;
    }
    
    .match-score {
        background: linear-gradient(135deg, #667eea, #764ba2);
        color: white;
        padding: 0.3rem 0.8rem;
        border-radius: 20px;
        font-size: 0.85rem;
        font-weight: 500;
    }
    
    .job-rec-company {
        font-weight: 600;
        color: #667eea;
        margin-bottom: 0.3rem;
    }
    
    .job-rec-location, .job-rec-salary {
        color: var(--text-secondary);
        margin-bottom: 0.3rem;
    }
    
    .job-rec-skills {
        color: var(--text-muted);
        font-size: 0.9rem;
        margin-bottom: 1rem;
    }
    
    .strategy-list ul {
        list-style: none;
        padding: 0;
    }
    
    .strategy-list li {
        background: rgba(102, 126, 234, 0.05);
        padding: 0.8rem;
        margin-bottom: 0.5rem;
        border-radius: 6px;
        border-left: 3px solid #667eea;
    }
    
    .answer-item, .tip-item {
        background: var(--bg-secondary);
        padding: 1rem;
        margin-bottom: 1rem;
        border-radius: 6px;
        border-left: 3px solid #667eea;
    }
    
    .answer-item h5, .tip-item h5 {
        color: var(--text-primary);
        margin-bottom: 0.5rem;
    }
    
    .tip-item h5 i {
        color: #667eea;
        margin-right: 0.5rem;
    }
    
    .loading-message {
        text-align: center;
        padding: 2rem;
        color: var(--text-secondary);
    }
    
    .loading-message i {
        font-size: 2rem;
        color: #667eea;
        margin-bottom: 1rem;
    }
    
    /* AI聊天界面样式 */
    .chat-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 1rem;
        border-bottom: 1px solid var(--border-light);
        background: var(--bg-secondary);
        border-radius: 8px 8px 0 0;
    }
    
    .chat-title {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        font-weight: 600;
        color: var(--text-primary);
    }
    
    .chat-title i {
        color: #667eea;
        font-size: 1.2rem;
    }
    
    .chat-actions {
        display: flex;
        gap: 0.5rem;
    }
    
    .ai-status-banner {
        padding: 0.8rem;
        margin-bottom: 1rem;
        border-radius: 6px;
        display: flex;
        align-items: center;
        gap: 0.5rem;
        font-size: 0.9rem;
    }
    
    .ai-status-banner.success {
        background: rgba(34, 197, 94, 0.1);
        color: #16a34a;
        border: 1px solid rgba(34, 197, 94, 0.2);
    }
    
    .ai-status-banner.warning {
        background: rgba(245, 158, 11, 0.1);
        color: #d97706;
        border: 1px solid rgba(245, 158, 11, 0.2);
    }
    
    .message-time {
        font-size: 0.75rem;
        color: var(--text-muted);
        margin-top: 0.5rem;
        display: block;
    }
    
    .message.loading {
        opacity: 0.7;
    }
    
    .quick-question {
        background: rgba(102, 126, 234, 0.1);
        border: 1px solid rgba(102, 126, 234, 0.2);
        color: #667eea;
        padding: 0.5rem 1rem;
        border-radius: 20px;
        font-size: 0.85rem;
        margin: 0.25rem;
        cursor: pointer;
        transition: all 0.3s ease;
    }
    
    .quick-question:hover {
        background: rgba(102, 126, 234, 0.2);
        transform: translateY(-1px);
    }
    
    .btn-outline {
        background: transparent;
        border: 1px solid var(--border-light);
        color: var(--text-secondary);
        transition: all 0.3s ease;
    }
    
    .btn-outline:hover {
        background: var(--bg-secondary);
        color: var(--text-primary);
        border-color: #667eea;
    }
    
    .btn-sm {
        padding: 0.4rem 0.8rem;
        font-size: 0.85rem;
    }
`;
document.head.appendChild(newStyles);

// ===== 分割条拖拽功能 =====
let splitterDragging = false;
let splitterStartX = 0;
let leftPanelStartWidth = 0;
let rightPanelStartWidth = 0;

function initSplitterDrag() {
    const splitter = document.getElementById('chartModalSplitter');
    const leftPanel = document.getElementById('chartModalLeftPanel');
    const rightPanel = document.getElementById('chartModalRightPanel');
    const contentWrapper = document.getElementById('chartModalContentWrapper');
    
    if (!splitter || !leftPanel || !rightPanel) return;
    
    splitter.addEventListener('mousedown', startDrag);
    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', endDrag);
    
    function startDrag(e) {
        e.preventDefault();
        splitterDragging = true;
        splitterStartX = e.clientX;
        
        // 获取当前宽度
        leftPanelStartWidth = leftPanel.offsetWidth;
        rightPanelStartWidth = rightPanel.offsetWidth;
        
        // 添加拖拽样式
        splitter.classList.add('dragging');
        document.body.classList.add('splitter-dragging');
        
        // 临时禁用过渡动画
        leftPanel.style.transition = 'none';
        rightPanel.style.transition = 'none';
    }
    
    function drag(e) {
        if (!splitterDragging) return;
        
        e.preventDefault();
        const deltaX = e.clientX - splitterStartX;
        const contentWrapperWidth = contentWrapper.offsetWidth;
        const splitterWidth = 5; // 分割条宽度
        
        // 计算新的宽度
        let newLeftWidth = leftPanelStartWidth + deltaX;
        let newRightWidth = rightPanelStartWidth - deltaX;
        
        // 设置最小和最大宽度限制
        const minWidth = 300;
        const maxLeftWidth = contentWrapperWidth * 0.7; // 左栏最大70%
        const maxRightWidth = contentWrapperWidth * 0.7; // 右栏最大70%
        
        // 应用限制
        if (newLeftWidth < minWidth) {
            newLeftWidth = minWidth;
            newRightWidth = contentWrapperWidth - newLeftWidth - splitterWidth;
        } else if (newRightWidth < minWidth) {
            newRightWidth = minWidth;
            newLeftWidth = contentWrapperWidth - newRightWidth - splitterWidth;
        } else if (newLeftWidth > maxLeftWidth) {
            newLeftWidth = maxLeftWidth;
            newRightWidth = contentWrapperWidth - newLeftWidth - splitterWidth;
        } else if (newRightWidth > maxRightWidth) {
            newRightWidth = maxRightWidth;
            newLeftWidth = contentWrapperWidth - newRightWidth - splitterWidth;
        }
        
        // 应用新宽度
        leftPanel.style.width = newLeftWidth + 'px';
        rightPanel.style.width = newRightWidth + 'px';
    }
    
    function endDrag() {
        if (!splitterDragging) return;
        
        splitterDragging = false;
        
        // 移除拖拽样式
        splitter.classList.remove('dragging');
        document.body.classList.remove('splitter-dragging');
        
        // 恢复过渡动画
        setTimeout(() => {
            leftPanel.style.transition = 'width 0.3s ease';
            rightPanel.style.transition = 'width 0.3s ease';
        }, 10);
    }
}

// 重置分割条位置到默认状态
function resetSplitterPosition() {
    const leftPanel = document.getElementById('chartModalLeftPanel');
    const rightPanel = document.getElementById('chartModalRightPanel');
    const contentWrapper = document.getElementById('chartModalContentWrapper');
    
    if (!leftPanel || !rightPanel || !contentWrapper) return;
    
    const contentWidth = contentWrapper.offsetWidth;
    const defaultRightWidth = 400;
    const defaultLeftWidth = contentWidth - defaultRightWidth - 5; // 减去分割条宽度
    
    leftPanel.style.width = defaultLeftWidth + 'px';
    rightPanel.style.width = defaultRightWidth + 'px';
}

// 双击分割条重置位置
function initSplitterDoubleClick() {
    const splitter = document.getElementById('chartModalSplitter');
    if (!splitter) return;
    
    splitter.addEventListener('dblclick', (e) => {
        e.preventDefault();
        resetSplitterPosition();
    });
}

// 窗口大小改变时调整布局
function handleSplitterResize() {
    const leftPanel = document.getElementById('chartModalLeftPanel');
    const rightPanel = document.getElementById('chartModalRightPanel');
    const contentWrapper = document.getElementById('chartModalContentWrapper');
    
    if (!leftPanel || !rightPanel || !contentWrapper) return;
    
    const contentWidth = contentWrapper.offsetWidth;
    const currentLeftWidth = leftPanel.offsetWidth;
    const currentRightWidth = rightPanel.offsetWidth;
    const splitterWidth = 5;
    
    // 检查当前宽度是否超出容器
    if (currentLeftWidth + currentRightWidth + splitterWidth > contentWidth) {
        // 按比例调整
        const totalCurrentWidth = currentLeftWidth + currentRightWidth;
        const availableWidth = contentWidth - splitterWidth;
        
        const leftRatio = currentLeftWidth / totalCurrentWidth;
        const rightRatio = currentRightWidth / totalCurrentWidth;
        
        const newLeftWidth = Math.max(300, availableWidth * leftRatio);
        const newRightWidth = Math.max(300, availableWidth * rightRatio);
        
        leftPanel.style.width = newLeftWidth + 'px';
        rightPanel.style.width = newRightWidth + 'px';
    }
}

// 当AI面板显示时初始化分割条
function initializeSplitter() {
    // 延迟初始化，确保DOM已经渲染
    setTimeout(() => {
        initSplitterDrag();
        initSplitterDoubleClick();
        resetSplitterPosition();
    }, 100);
}

// 监听窗口大小变化
window.addEventListener('resize', () => {
    if (document.getElementById('chartModalRightPanel')?.classList.contains('show')) {
        handleSplitterResize();
    }
}); 

// 本地存储键
const FAVORITES_KEY = 'jh_fav_jobs';
const COMPARE_KEY = 'jh_compare_jobs';
const COMPARE_LIMIT = 3;

function loadIdSet(key) {
    try {
        const raw = localStorage.getItem(key);
        const arr = raw ? JSON.parse(raw) : [];
        return new Set(arr);
    } catch { return new Set(); }
}

function saveIdSet(key, set) {
    try { localStorage.setItem(key, JSON.stringify(Array.from(set))); } catch {}
}

function ensureRecommendedMeta(container) {
    const card = container.closest('.analysis-card');
    if (!card) return;
    const header = card.querySelector('.card-header');
    if (!header) return;
    let meta = header.querySelector('#recommendedMeta');
    if (!meta) {
        meta = document.createElement('div');
        meta.id = 'recommendedMeta';
        meta.style.display = 'flex';
        meta.style.gap = '8px';
        meta.style.marginLeft = 'auto';
        meta.innerHTML = `
            <span id="compareCount" class="job-badge" title="查看对比" style="cursor:pointer">对比(0)</span>
            <span id="favoriteCount" class="job-badge">收藏(0)</span>
        `;
        header.appendChild(meta);
        const cmp = meta.querySelector('#compareCount');
        if (cmp) {
            cmp.addEventListener('click', openCompareModal);
        }
    }
    updateRecommendedMeta();
}

function updateRecommendedMeta() {
    const compare = loadIdSet(COMPARE_KEY);
    const fav = loadIdSet(FAVORITES_KEY);
    const cmpEl = document.getElementById('compareCount');
    const favEl = document.getElementById('favoriteCount');
    if (cmpEl) cmpEl.textContent = `对比(${compare.size})`;
    if (favEl) favEl.textContent = `收藏(${fav.size})`;
}

function syncCompareButtons() {
    const compareSet = loadIdSet(COMPARE_KEY);
    document.querySelectorAll('[data-action="compare"]').forEach(btn => {
        const id = btn.getAttribute('data-id');
        const isOn = compareSet.has(id);
        btn.textContent = isOn ? '已加入对比' : '对比';
        btn.classList.toggle('active', isOn);
    });
}

function attachRecommendedPositionHandlers(container, positions) {
    const byId = new Map();
    positions.forEach(p => {
        const key = String(p.id || p.job_id || p.url || (p.title + '|' + p.company + '|' + p.location));
        byId.set(key, p);
    });

    const compareSet = loadIdSet(COMPARE_KEY);
    const favSet = loadIdSet(FAVORITES_KEY);

    container.querySelectorAll('[data-action="compare"]').forEach(btn => {
        const id = btn.getAttribute('data-id');
        const isOn = compareSet.has(id);
        btn.textContent = isOn ? '已加入对比' : '对比';
        btn.classList.toggle('active', isOn);
        btn.addEventListener('click', () => {
            const currentlyOn = compareSet.has(id);
            if (!currentlyOn && compareSet.size >= COMPARE_LIMIT) {
                alert(`最多选择 ${COMPARE_LIMIT} 个职位进行对比`);
                return;
            }
            if (currentlyOn) compareSet.delete(id); else compareSet.add(id);
            saveIdSet(COMPARE_KEY, compareSet);
            btn.textContent = compareSet.has(id) ? '已加入对比' : '对比';
            btn.classList.toggle('active', compareSet.has(id));
            updateRecommendedMeta();
        });
    });

    container.querySelectorAll('[data-action="favorite"]').forEach(btn => {
        const id = btn.getAttribute('data-id');
        const isOn = favSet.has(id);
        btn.textContent = isOn ? '已收藏' : '收藏';
        btn.classList.toggle('active', isOn);
        btn.addEventListener('click', () => {
            const currentlyOn = favSet.has(id);
            if (currentlyOn) favSet.delete(id); else favSet.add(id);
            saveIdSet(FAVORITES_KEY, favSet);
            btn.textContent = favSet.has(id) ? '已收藏' : '收藏';
            btn.classList.toggle('active', favSet.has(id));
            updateRecommendedMeta();
        });
    });

    container.querySelectorAll('[data-action="detail"]').forEach(btn => {
        const id = btn.getAttribute('data-id');
        const job = byId.get(id);
        const url = job && (job.url || job.jd_url || job.link);
        btn.addEventListener('click', () => {
            if (url) {
                window.open(url, '_blank');
            } else {
                const q = encodeURIComponent(`${job?.title || ''} ${job?.company || ''}`.trim());
                window.open(`https://www.bing.com/search?q=${q}`, '_blank');
            }
        });
    });

    updateRecommendedMeta();
}

// ===== 对比面板与推荐增强 =====

function getCompareItems() {
    const set = loadIdSet(COMPARE_KEY);
    return Array.from(set);
}

function openCompareModal() {
    const ids = getCompareItems();
    if (ids.length === 0) {
        alert('请先在推荐职位中选择要对比的职位');
        return;
    }
    ensureCompareModal();
    renderCompareTable(ids);
    document.getElementById('compareModal').classList.add('show');
}

function closeCompareModal() {
    const modal = document.getElementById('compareModal');
    if (modal) modal.classList.remove('show');
}

function ensureCompareModal() {
    if (document.getElementById('compareModal')) return;
    const modal = document.createElement('div');
    modal.id = 'compareModal';
    modal.className = 'chart-modal';
    modal.innerHTML = `
        <div class="chart-modal-content compare-modal-content">
            <div class="chart-modal-header">
                <h3><i class="fas fa-columns"></i> 职位对比</h3>
                <div class="chart-modal-header-controls">
                    <button class="chart-modal-close" title="关闭" onclick="closeCompareModal()">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
            </div>
            <div class="chart-modal-body">
                <div class="compare-toolbar">
                    <label><input type="checkbox" id="highlightDiff" checked> 高亮差异</label>
                    <button class="btn btn-secondary" onclick="clearCompareSelection()">清空对比</button>
                </div>
                <div class="compare-table-wrapper">
                    <table class="compare-table" id="compareTable"></table>
                </div>
            </div>
        </div>`;
    document.body.appendChild(modal);

    // 事件
    modal.addEventListener('click', (e)=>{
        if (e.target === modal) closeCompareModal();
    });
    const highlight = modal.querySelector('#highlightDiff');
    if (highlight) highlight.addEventListener('change', ()=>{
        // 重新渲染以应用高亮
        const ids = getCompareItems();
        renderCompareTable(ids);
    });
}

function clearCompareSelection() {
    saveIdSet(COMPARE_KEY, new Set());
    updateRecommendedMeta();
    syncCompareButtons();
    renderCompareTable([]);
}

function renderCompareTable(ids) {
    const table = document.getElementById('compareTable');
    if (!table) return;
    if (!ids || ids.length === 0) {
        table.innerHTML = '<tbody><tr><td style="padding:20px">暂无对比项</td></tr></tbody>';
        return;
    }

    // 组装基础字段
    const items = ids.map(id => findJobById(id)).filter(Boolean);
    const fields = [
        { key: 'title', label: '职位' },
        { key: 'company', label: '公司' },
        { key: 'location', label: '地点' },
        { key: 'salary_range', label: '薪资' },
        { key: 'type', label: '类型' },
        { key: 'match_score', label: '匹配度' },
        { key: 'skills', label: '关键词/技能' }
    ];

    // 差异检测
    const highlight = document.getElementById('highlightDiff');
    const shouldHighlight = highlight ? highlight.checked : true;

    const header = ['对比项', ...items.map((_, idx) => `职位 ${idx+1}`)];
    let html = '<thead><tr>' + header.map(h => `<th>${h}</th>`).join('') + '</tr></thead><tbody>';

    // 移除按钮行
    html += '<tr>' + ['操作', ...items.map((it, idx)=>
        `<td><button class="btn btn-outline btn-sm" onclick="removeFromCompare('${ids[idx]}')">移除</button></td>`) ].map((c,i)=> i===0?`<td class="row-label">${c}</td>`:`${c}`).join('') + '</tr>';

    for (const field of fields) {
        const values = items.map(it => normalizeFieldValue(it, field.key));
        const allSame = values.every(v => v === values[0]);
        html += '<tr>';
        html += `<td class="row-label">${field.label}</td>`;
        values.forEach(v => {
            const cls = shouldHighlight && !allSame ? 'diff' : '';
            html += `<td class="${cls}">${v || '-'}</td>`;
        });
        html += '</tr>';
    }

    table.innerHTML = html + '</tbody>';
}

function removeFromCompare(id) {
    const set = loadIdSet(COMPARE_KEY);
    set.delete(id);
    saveIdSet(COMPARE_KEY, set);
    updateRecommendedMeta();
    syncCompareButtons();
    const ids = Array.from(set);
    renderCompareTable(ids);
}

function normalizeFieldValue(job, key) {
    if (!job) return '';
    if (key === 'skills') {
        if (Array.isArray(job.tags)) return job.tags.join(', ');
        if (job.skills) return String(job.skills);
        return '';
    }
    if (key === 'match_score') {
        const v = Number(job.match_score);
        if (!isFinite(v)) return '';
        return `${Math.max(0, Math.min(100, Math.round(v)))}%`;
    }
    return job[key] == null ? '' : String(job[key]);
}

function findJobById(id) {
    // 从当前推荐位/分析结果中尝试获取
    const cardsContainer = document.getElementById('recommendedPositions');
    if (cardsContainer) {
        const card = cardsContainer.querySelector(`.job-card[data-id="${CSS.escape(id)}"]`);
        if (card) {
            // 从 DOM 上无法得到完整数据，优先从 lastAnalysisData.recommended_positions 查找
        }
    }
    const positions = (window.lastAnalysisData && window.lastAnalysisData.recommended_positions) || [];
    const job = positions.find(p => String(p.id || p.job_id || p.url || (p.title + '|' + p.company + '|' + p.location)) === String(id));
    if (job) return job;
    // 兜底：从收藏或本地缓存中找
    try {
        const cached = JSON.parse(localStorage.getItem('jh_cached_jobs') || '[]');
        return cached.find(p => String(p.id || p.job_id || p.url) === String(id));
    } catch { return null; }
}

// 推荐职位增强：分页/加载更多与补充推荐
function setupRecommendedPositionsEnhancements(container, positions) {
    // 如果职位少于 6 条，尝试补充
    if (!positions || positions.length < 6) {
        fetchSupplementalRecommendations(positions).then(supp => {
            const merged = mergeRecommendations(positions, supp);
            renderRecommendedWithControls(container, merged);
        }).catch(()=>{
            renderRecommendedWithControls(container, positions);
        });
    } else {
        renderRecommendedWithControls(container, positions);
    }
}

function renderRecommendedWithControls(container, allPositions) {
    // 缓存到 localStorage，便于对比表在刷新后查找
    try { localStorage.setItem('jh_cached_jobs', JSON.stringify(allPositions.slice(0, 100))); } catch {}

    // 直接渲染所有职位，移除"加载更多"，由容器滚动展示
    const sanitize = (v) => (v == null ? '' : String(v));
    let html = '<div class="job-list">';
    allPositions.forEach(position => {
        const tags = Array.isArray(position.tags) ? position.tags : (position.skills || '').split(',').slice(0,6);
        const jobId = sanitize(position.id || position.job_id || position.url || (position.title + '|' + position.company + '|' + position.location));
        const match = Math.max(0, Math.min(100, Number(position.match_score)||0));
        html += `
            <div class="job-item job-card" data-id="${jobId}">
                <div class="job-item-main">
                    <div class="job-item-title">
                        <h4>${sanitize(position.title)}</h4>
                        <span class="job-badge">${sanitize(position.type || '全职')}</span>
                    </div>
                    <div class="job-item-company">
                        <span class="company-name">${sanitize(position.company)}</span>
                        <span class="separator">·</span>
                        <span class="job-location"><i class="fas fa-map-marker-alt"></i>${sanitize(position.location)}</span>
                        <span class="separator">·</span>
                        <span class="job-salary"><i class="fas fa-yen-sign"></i>${sanitize(position.salary_range)}</span>
                    </div>
                    <div class="job-item-tags">
                        ${tags.filter(Boolean).map(t => `<span class=\"job-tag\">${sanitize(t).trim()}</span>`).join('')}
                    </div>
                </div>
                <div class="job-item-side">
                    <span class="job-match-pill">${match}%</span>
                    <div class="job-item-actions">
                        <button class="btn btn-outline btn-sm" data-action="compare" data-id="${jobId}">对比</button>
                        <button class="btn btn-secondary btn-sm" data-action="favorite" data-id="${jobId}">收藏</button>
                        <button class="btn btn-primary btn-sm" data-action="detail" data-id="${jobId}">查看详情</button>
                    </div>
                </div>
            </div>`;
    });
    html += '</div>';

    container.innerHTML = html;
    attachRecommendedPositionHandlers(container, allPositions);
    ensureRecommendedMeta(container);
}

function mergeRecommendations(primary, supplemental) {
    const list = [...(primary || [])];
    const exist = new Set(list.map(p => String(p.id || p.job_id || p.url || (p.title + '|' + p.company + '|' + p.location))));
    (supplemental || []).forEach(p => {
        const key = String(p.id || p.job_id || p.url || (p.title + '|' + p.company + '|' + p.location));
        if (!exist.has(key)) list.push(p);
    });
    return list;
}

async function fetchSupplementalRecommendations(currentPositions) {
    // 基于技能与目标职位，使用已有 /jobs 接口补充
    try {
        const base = (window.jhDashboard && jhDashboard.apiBaseUrl) || 'http://localhost:8000/api/jh';
        const skills = Object.keys((window.lastAnalysisData && window.lastAnalysisData.skill_matches) || {}).slice(0, 5);
        const query = skills.join(' ');
        const params = new URLSearchParams();
        if (query) params.set('search_query', query);
        params.set('page', '1');
        params.set('page_size', '24');
        const resp = await fetch(`${base}/jobs?${params.toString()}`);
        if (!resp.ok) throw new Error('supplemental fetch failed');
        const data = await resp.json();
        return data.jobs || [];
    } catch (e) {
        console.warn('补充推荐失败：', e);
        return [];
    }
}